
    
3j§                        S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
Js  Jr  S SKJr  S SKJrJr  S SKJr  S SKJr  S SKJr  SSKJr  SS	KJrJrJr   S*S
\S\S\4S jjr " S S5      r  " S S5      r! " S S5      r" " S S5      r# " S S5      r$S SK%r%S SK&r& " S S5      r' " S S5      r( " S S5      r) " S S5      r* " S  S!5      r+ " S" S#5      r, " S$ S%5      r- " S& S'5      r. " S( S)5      r/\#\"\$\/\(\*\+\,\-\.\'\)\!\ /r0g)+    N)model_management)ImageImageOps)PngInfo)gaussian)compare_images   )log)	np2tensor
pil2tensor
tensor2pilkernel_sizesigma_xsigma_yc           
         [         R                  " [         R                  " SSXS9[         R                  " SSXS9SS9u  pEXD-  SU-  U-  -  nXU-  SU-  U-  -  n[         R                  " Xg-   * 5      nXR	                  5       -  $ )N   deviceij)indexing       @)torchmeshgridlinspaceexpsum)	r   r   r   r   xyd_xd_ygs	            M/home/wildlama/comfy/ComfyUI/custom_nodes/comfy_mtb/nodes/image_processing.pygaussian_kernelr$      s     >>r1k9r1k9DA
 %3=7*
+C
%3=7*
+C		CI,Auuw;    c                   b    \ rS rSrSrSrSr\S 5       rS\	\	\
\\4         S\S\
\   4S	 jrS
rg)MTB_CoordinatesToString(   )STRINGconvertmtb/coordinatesc                     SSSS.0$ )Nrequired)BATCH_COORDINATES)INT)coordinatesframe clss    r#   INPUT_TYPES#MTB_CoordinatesToString.INPUT_TYPES-   s     5!
 	
r%   r0   r1   returnc                     [        U[        U5      S-
  5      nX   n/ nU H  u  pVUR                  XVS.5        M     [        R                  " U5      4$ )Nr   )r   r   )maxlenappendjsondumps)selfr0   r1   coordsoutputr   r   s          r#   r*   MTB_CoordinatesToString.convert6   sV     E3{+a/0#')DAMM*+  

6"$$r%   r2   N)__name__
__module____qualname____firstlineno__RETURN_TYPESFUNCTIONCATEGORYclassmethodr5   listtupleintstrr*   __static_attributes__r2   r%   r#   r'   r'   (   sV    LH H
 

%U38_ 56
%?B
%	s
%r%   r'   c                      \ rS rSrSrSrSrSr\S 5       r	  SS\
S	\S
\R                  S-  S\R                  S-  S\\\\\\4         \R                  4   4
S jjr\S
\R                  S\\\4   S\S\R                  4S j5       rSrg)MTB_ExtractCoordinatesFromImageC   z>Extract 2D points from a batch of images based on a threshold.)r.   IMAGEextractr+   c                 0    SSSSSS.4SSS	S
.4S.SSS.S.$ )NFLOAT      ?              ?{Gz?defaultminr9   stepr/   2   r   r[   r\   )	threshold
max_pointsrR   MASK)imagemaskr-   optionalr2   r3   s    r#   r5   +MTB_ExtractCoordinatesFromImage.INPUT_TYPESJ   s@    
  #CTJ  %"Q&?@ #-i@	
 		
r%   Nr`   ra   re   rf   r7   c                 r   Uc  Uc  [        S5      eUb  UR                  u  pVpxUR                  n	Ub  UR                  S:X  a  UR	                  S5      nUR                  S:w  a  [        SUR                   S35      eUR                  u  pnX:X  a  X:X  d  [        SU SU S	U SU S
3	5      eU
S:X  a  US:  a  UR                  XVU5      nO}X:w  a  [        SU SU
 S35      eOeUR                  S:X  a  UR	                  S5      nUR                  S:w  a  [        SUR                   S35      eUR                  u  pVnUR                  n	/ n[        R                  " XVUS4[        R                  U	S9n[        R                  " / SQ[        R                  U	S9n[        U5       GH  nUbi  UU   nUR                  S   nUS:X  d  US:X  a  US S 2S S 2S4   nOCUS:X  d  US:X  a  US S 2S S 2S S24   R                  SS9S   nO[        SU SU 35      eUU   nUnUU:  nUb  Ub  UU   nUS:  nUU-  nUR                  SS9nUR                  S5      U:  a-  [        R                  " UR                  S5      U	S9S U nUU   nO*US:X  a$  [        R                  " S[        R                   U	S9nU Vs/ s H;  n[#        US   R%                  5       5      [#        US   R%                  5       5      4PM=     nnUR'                  U5        U H  u  nnU R)                  UU   UU4SUS9  M     GM     X4$ s  snf )Nz!Must provide either image or maskr	   r      zMask has unexpected ndim: z. Expected 2 or 3.zImage dimensions (r   z) and mask dimensions (z) are spatially incompatible.r   zImage batch size (z) and mask batch size (z0) are incompatible and mask cannot be broadcast.z- when image is not provided. Expected 2 or 3.)dtyper   )   rm   rm      dimz!Unsupported image channel count: z for image at batch index rW   F)as_tupler   )r   r	      )radiuscolor_tensor)
ValueErrorshaper   ndim	unsqueezeexpandr   zerosuint8tensorranger9   nonzerosizerandpermemptylongrL   itemr;   _draw_circle)r>   r`   ra   re   rf   batch_countheightwidth_channel_countinput_deviceb_maskh_maskw_mask
all_pointsdebug_imagespoints_tensori	img_sliceimg_channelsvalue_threshold
mask_slice	conditionmask_active_condition	points_yxindicespcurrent_pointsx_coordy_coords                                r#   rS   'MTB_ExtractCoordinatesFromImage.extractW   s    =T\@AA9>6K <<L99>>>!,D99>$4TYYK?QR  *.&(V_$,VHAeW<STZS[[\]c\d  eB  C  Q;;?;;{EBD*$,[M9PQWPX  YI  J  yyA~~~a(yyA~ 0;hi  *.&K;;L24
{{%+++
 5;;|
 {#A !!H	(q11$(9&/1a&8O!Q&,!*;&/1bqb&9&=&=!&=&DQ&GO$;L>Icdecfg  "!W
",')3I T%5!!W
(2S(8%%(==	!))5)9I~~a :-..NN1%l: &g.	q!KK%**\	
 ?H>GQqTYY[!3qtyy{#34i   n-$2 !! Og&!.	 "  %3Q $` ))s   4AL4centerrs   rt   c                 4   Uu  pEU R                   u  pgn[        SXB-
  5      n	[        US-
  XB-   5      n
[        SXR-
  5      n[        US-
  XR-   5      n[        XS-   5       H5  n[        XS-   5       H   nX-
  S-  X-
  S-  -   US-  ::  d  M  X0X4'   M"     M7     g)zDraw a 5px circle on the image.r   r   r	   N)rv   r9   r\   r}   )re   r   rs   rt   x0y0hw_
min_x_bbox
max_x_bbox
min_y_bbox
max_y_bboxpypxs                  r#   r   ,MTB_ExtractCoordinatesFromImage._draw_circle   s     ++aBK(
Q,
BK(
Q,

N3BJQ7G>RWN2fai?$0"&M 8 4r%   r2   NN)rB   rC   rD   rE   __doc__rF   rG   rH   rI   r5   floatrL   r   TensorrK   rJ   rS   staticmethodr   rN   r2   r%   r#   rP   rP   C   s    H1LH H

 

  &*$(h*h* h* ||d"	h*
 llT!h* 
tDsCx)*ELL8	9h*T 1||1c3h1 1 ll	1 1r%   rP   c                   4   \ rS rSrSr\S 5       rSrSrSr	\
S\R                  S\4S	 j5       r\
S
\R                  4S j5       r\
S\R                  4S j5       r        SS
\R                  S\S\S\S\S\S\S\S\S\S\R                  S-  4S jjrSrg)MTB_ColorCorrectGPU   z2Various color correction methods using only Torch.c                     SSSS04SS/SS04SSSS	S
S.4SSSS	S
S.4SSSS	S
S.4SSSS	S
S.4SSSSS
S.4SSSS	S
S.4SSSS	S
S.4S.
SS0S.$ )Nrb   BOOLEANr[   TFrU   rX   rW         @rY   rZ               rV   )
re   	force_gpuclampgammacontrastexposureoffsethue
saturationvaluerf   rc   rg   r2   r3   s    r#   r5   MTB_ColorCorrectGPU.INPUT_TYPES   s     $')T):;-)T):; #CTJ
  #CTJ
  #DdK
  #DdK
  #DdK
  #CTJ
  #CTJ9 B  +E#
 #	
r%   rb   correctmtb/image processingr|   r   c                    U(       a  [         R                  R                  5       (       a  [         R                  " S5      $ [	        [         R
                  S5      (       aC  [         R
                  R                  R                  5       (       a  [         R                  " S5      $ [	        [         S5      (       a9  [         R                  R                  5       (       a  [         R                  " S5      $ U R                  $ )Ncudampship)r   r   is_availabler   hasattrbackendsr   r   )r|   r   s     r#   
get_deviceMTB_ColorCorrectGPU.get_device  s    zz&&((||F++..NN&&3355||E**&&599+A+A+C+C||E**MM	
r%   re   c                    U R                  S5      u  pnU R                  S5      u  pEU R                  S5      u  pgXF-
  n[        R                  " U5      n	XS-   -  n
UnX#-
  US:H     US-   US:H     -  XS:H  '   SX1-
  US:H     US-   US:H     -  -   XS:H  '   SX-
  US:H     US-   US:H     -  -   XS:H  '   U	S-  S	-  n	U	R                  S5      n	U
R                  S5      n
UR                  S5      n[        R                  " XU4SS
9$ )Nr   Hz>r   r   r         @r	         @rX   ro   )unbindr9   r\   r   
empty_likerx   cat)re   rr"   bmax_rgb
argmax_rgbmin_rgbr   diffr   svs               r#   
rgb_to_hsvMTB_ColorCorrectGPU.rgb_to_hsv  s;   ,,r"a#iimYYr]
 W%dN#eZ1_5!O9
 
/ 15*/*dTk:?-KKK 	
/ 15*/*dTk:?-KKK 	
/ WOKKOKKOKKOyy!++r%   hsvc                 H   U R                  S5      u  pnUS-  n[        R                  " U5      nX-
  nUSU-
  -  nUSX%-  -
  -  nUSUSU-
  -  -
  -  nUR                  5       S-  n[        R                  " US:H  US:H  US:H  US:H  US	:H  US
:H  4S5      n	[        R                  " [        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   X5      5      5      5      5      [        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   Xf5      5      5      5      5      [        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   U[        R
                  " U	S   X75      5      5      5      5      4SS9n
U
$ )Nr   r   rX      r   r   r	   rk   rn   rr   .r   .r   .r	   ).rk   ).rn   ro   )r   r   floorr   stackwhere)r   r   r   r   r   fr   qtrf   rgbs              r#   
hsv_to_rgbMTB_ColorCorrectGPU.hsv_to_rgb1  s   **R.aGKKNEqMquqC!G}$%FFHqL{{!VQ!VQ!VQ!VQ!VQ!V<b
 kkLKKV L!KK $V ! %DL! ?" LKKV L!KK $V ! %DL! ?" LKKV L!KK $V ! %DL! ?G4j m7
r 
r%   Nr   r   r   r   r   r   r   r   rf   c                 .   U R                  X5      nUR                  U5      nUbt  UR                  S   UR                  S   :w  a   UR                  UR                  S   SS5      nUR	                  S5      R                  SSSS5      nUR                  U5      n[
        R                  " 5         UR                  SU-  5      SU-  -  U-  U-   n[
        R                  " 5         U R                  U5      nUS   U-   S-  US'   US   U	-  US'   US	   U
-  US	'   U R                  U5      n[
        R                  " 5         U(       a  [        R                  " US
S5      nUc  UO[        R                  " US:  X5      nU(       d  UR                  5       nU4$ )Nr   r   rk   r   r   r   rX   r   r   rW   )r   torv   ry   rx   r   )throw_exception_if_processing_interruptedpowr   r   r   r   r   cpu)r>   re   r   r   r   r   r   r   r   r   r   rf   r   adjustedr   results                   r#   r   MTB_ColorCorrectGPU.correct}  st    2 zz!}A.{{5;;q>2r:>>"%,,RR;D776?DBBD99QY'3=9HDvMBBDooh'6{S(C/F&kJ.F&kE)F??3'BBD{{8S#6H
 | TAXx7 	 ZZ\Fyr%   r2   rX   rX   rW   rW   rW   rX   rX   N)rB   rC   rD   rE   r   rI   r5   rF   rG   rH   r   r   r   boolr   r   r   r   r   rN   r2   r%   r#   r   r      s,   <$
 $
L LH%H
5<< 
D 
 
 ,%,, , ,8 I I I` $(0||0 0 	0
 0 0 0 0 0 0 0 llT!0 0r%   r   c                   @   \ rS rSrSr\S 5       rSrSrSr	\
S 5       r\
S 5       r\
S	 5       r\
S
 5       r\
S\R                   4S j5       r\
S\R                   4S j5       r        SS\R                   S\S\S\S\S\S\S\S\S\R                   S-  4S jjrSrg)MTB_ColorCorrecti  z Various color correction methodsc                     SSS/SS04SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4SSSSS	S
.4S.	SS0S.$ )Nrb   TFr[   rU   rX   rW   r   rY   rZ   r   r   rV   )	re   r   r   r   r   r   r   r   r   rf   rc   rg   r2   r3   s    r#   r5   MTB_ColorCorrect.INPUT_TYPES  s     $-)T):; #CTJ
  #CTJ
  #DdK
  #DdK
  #DdK
  #CTJ
  #CTJ7@  +C"
 "	
r%   rb   r   r   c                 .    SU-  nU R                  U5      $ )NrX   )r   )re   r   	gamma_invs      r#   gamma_correction_tensor(MTB_ColorCorrect.gamma_correction_tensor  s    %K	yy##r%   c                     U R                  S5      u  p#nSU-  SU-  -   SU-  -   n[        R                  " UR                  S5      5      nX-  SU-
  U-  -   n[        R                  " USS5      $ )Nr   gQ?gQ?gQ?rX   rW   )r   r   meanrx   r   )re   r   r   r"   r   luminance_imageluminance_mean
contrasteds           r#   contrast_adjustment_tensor+MTB_ColorCorrect.contrast_adjustment_tensor  su    ,,r"a (TAX-q8O$=$=b$AB %x>(II
{{:sC00r%   c                     U SU-  -  $ )Nr   r2   )re   r   s     r#   exposure_adjustment_tensor+MTB_ColorCorrect.exposure_adjustment_tensor  s    X&&r%   c                 
    X-   $ Nr2   )re   r   s     r#   offset_adjustment_tensor)MTB_ColorCorrect.offset_adjustment_tensor  s
    ~r%   re   c                   ^^^ [        U 5      n/ nU H  nUR                  S5      nUR                  5       u  pn
UR                  U4S j5      nU	R                  U4S j5      n	U
R                  U4S j5      n
[        R
                  " SXU
45      nUR                  S5      nUR                  U5        M     [        U5      $ )NHSVc                    > U TS-  -   S-  $ )Nrm      r2   )r   r   s    r#   <lambda>1MTB_ColorCorrect.hsv_adjustment.<locals>.<lambda>  s    1sSy=C"7r%   c                     > [        U T-  5      $ r  rL   )r   r   s    r#   r  r     s    #a*n"5r%   c                     > [        U T-  5      $ r  r  )r   r   s    r#   r  r    s    #a%i.r%   RGB)r   r*   splitpointr   merger;   r   )re   r   r   r   imagesoutimg	hsv_imager   r   r   	rgb_images    ```        r#   hsv_adjustmentMTB_ColorCorrect.hsv_adjustment  s    E"CE*Ioo'GA!78A56A01AEA!95I!))%0IJJy!  #r%   c           
         U R                  S5      R                  SSS5      n U R                  SSS9u  pEU R                  SSS9u  peXF-
  n[        R
                  " U5      nUS:g  n	U S   U S   U S   pn
X-
  U-  XU
:H  -     S-  XXJ:H  -  '   X-
  U-  XU:H  -     S-   XXK:H  -  '   X-
  U-  XU:H  -     S	-   XXL:H  -  '   XtS
-   -  nUnX-   S-  n[        R                  " XU-  U5      nX>-  nX-  nUS[        R                  " US-  S-
  5      -
  -  nX-
  n[        R
                  " U 5      n[        R                  " XJ:H  U[        R                  " XK:H  UUS   5      5      US'   [        R                  " XJ:H  U[        R                  " XK:H  UUS   5      5      US'   [        R                  " XK:H  U[        R                  " XL:H  UUS   5      5      US'   UU-   nUR                  SSS5      R                  S5      nU$ )zAbandonning for nowr   r	   r   T)rp   keepdimrW   r   r   r   r   rX   )	squeezepermuter9   r\   r   
zeros_liker   absrx   )re   r   r   r   max_valr   min_valdelta	hue_imagerf   r   r"   r   saturation_imagevalue_imagecr   mprime_imager  s                       r#   !hsv_adjustment_tensor_not_working2MTB_ColorCorrect.hsv_adjustment_tensor_not_working  sL   
 a ((Aq1YY1dY3
YY1dY3
!$$W-	|(E!HeAha-.UeOqL!,
,	','( ./UeOqL!,
,	','( ./UeOqL!,
,	','( !dN3_+	 ;;//1A
 )*UYY	A2334O&&u-L!U[[q+a.I
A L!U[[q+a.I
A L!U[[q+a.I
A  !O	%%aA.88;	r%   Nr   r   r   r   r   r   r   r   rf   c                    U
bc  U
R                   S   UR                   S   :w  a   U
R                  UR                   S   SS5      n
U
R                  S5      R                  SSSS5      n
U R                  X5      nU R	                  X5      nU R                  X5      nU R                  X5      nU R                  XX5      nU(       a  [        R                  " USS5      nU
c  UnU4$ [        R                  " U
S:  X5      nU4$ )Nr   r   rk   rW   rX   )rv   ry   rx   r   r  r  r  r   r   r   r   )r>   re   r   r   r   r   r   r   r   r   rf   r   r   s                r#   r   MTB_ColorCorrect.correct?  s    zz!}A.{{5;;q>2r:>>"%,,RR;D //=228F228F00B&&xjH{{8S#6H |  	 y TAXx7 	 yr%   r2   r   )rB   rC   rD   rE   r   rI   r5   rF   rG   rH   r   r   r  r  r  r   r   r   r1  r   r   r   rN   r2   r%   r#   r   r     sJ   *#
 #
J LH%H$ $ 	1 	1 ' '   ell  " 4||4 4t $(#||# # 	#
 # # # # # # llT!# #r%   r   c                   n    \ rS rSrSr\S 5       rSrSrSr	S\
R                  S\
R                  4S	 jrS
rg)MTB_ImageCompareie  z0Compare two images and return a difference imagec                     SSS/ SQSS04S.0$ )Nr-   rb   )checkerboardr   blendr[   r8  )imageAimageBmoder2   r3   s    r#   r5   MTB_ImageCompare.INPUT_TYPESh  s,     $$5/	
 		
r%   rb   compare	mtb/imager:  r;  c                   ^ ^^^ TR                  5       S:X  aF  TR                  S5      n[        R                  " [	        UUUU 4S j[        U5       5       5      SS94$ TR                  S5      nTR                  S5      nUS:X  a>  US:X  a8  [        R                  " T[        R                  " TS S 2S S 2SS24   5      4SS9mOCUS:X  a=  US:X  a7  [        R                  " T[        R                  " TS S 2S S 2SS24   5      4SS9mT=S:X  a    [        R                  " TT-
  5      nO=S	:X  a
    S
TT-   -  nOS:X  a  TR                  5       mTR                  5       m[        TR                  S   5       Vs/ s H6  n[        R                  " [        TS S 2S S 2U4   TS S 2S S 2U4   TS95      PM8     n	n[        R                  " U	SS9nO S n[        ST 35      eUR                  S5      nU4$ s  snf )Nrn   r   c              3   \   >#    U  H!  nTR                  TU   TU   T5      S    v   M#     g7f)r   N)r>  ).0r   r:  r;  r<  r>   s     r#   	<genexpr>+MTB_ImageCompare.compare.<locals>.<genexpr>~  s2      !3A VAYq	4@C!3s   ),ro   r	   rk   r   r   r9  rV   r8  )methodzUnknown mode )rp   r   r   r   rK   r}   	ones_liker'  numpyrv   
from_numpyr   r   ru   rx   )
r>   r:  r;  r<  r   num_channels_Anum_channels_Bcompare_imager   compared_channelss
   ````      r#   r>  MTB_ImageCompare.comparey  s   ::<1 ++a.K		 !&{!3     QQ Q>Q#6YY1ac	):;<!F q ^q%8YY1ac	):;<!F  %		&6/ : #v 7 #6<<?3% 4 $$&"1a7OVAq!G_T
 4 " % !&,=1 E $ =!788%//2!%s   9=G3r2   N)rB   rC   rD   rE   r   rI   r5   rF   rG   rH   r   r   r>  rN   r2   r%   r#   r6  r6  e  sC    :

 

 LHH1 ell 1 ELL 1 r%   r6  c                   :    \ rS rSrSr\S 5       rSrSrSr	S r
Srg	)
MTB_LoadImageFromUrli  z Load an image from the given URLc           	      6    SSSS04SSSSSS	.4S
SSSSS	.4S.0$ )Nr-   r)   r[   zWhttps://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Example.jpg/800px-Example.jpgr/   rk   r      rZ   rU   rX   rW   g      N@皙?)urlretry_countretry_intervalr2   r3   s    r#   r5    MTB_LoadImageFromUrl.INPUT_TYPES  sU     !#|  !!BB 
  #CcJ#
 	
r%   rb   loadmtb/IOc                    S n[        U5       Hk  n [        R                  " USS9nUR                  5         [        R
                  " UR                  5      n[        R                  " U5      n[        U5      4s  $    Ub  Ue[        S5      e! [         a@  nUnXRS-
  :X  a  e USU-  -  n	U	S:  a  [        R                  " U	5         S nAM   S nAM  S nAff = f)NT)streamr   r	   r   z8Failed to load image from URL without captured exception)r}   requestsgetraise_for_statusr   openrawr   exif_transposer   	ExceptiontimesleepRuntimeError)
r>   rS  rT  rU  
last_errorattemptresponsere   ewait_secondss
             r#   rW  MTB_LoadImageFromUrl.load  s    
[)G-#<<D9))+

8<<0 //6"5)++ * !UVV  -
Ao--G<!#JJ|,, $-s   A&B
C/CCr2   N)rB   rC   rD   rE   r   rI   r5   rF   rG   rH   rW  rN   r2   r%   r#   rO  rO    s.    *
 
( LHHWr%   rO  c                   \    \ rS rSrSr\S 5       rSrSrSr	 SS\
R                  4S	 jjrS
rg)MTB_Bluri  z&Blur an image using a Gaussian filter.c                 6    SSSSSSS.4SSSSSS.4S.S	S	S
.S.$ )Nrb   rU   g      @rW   g      i@rY   rZ   )re   sigmaXsigmaY)FLOATS)sigmasXsigmasYrg   r2   r3   s    r#   r5   MTB_Blur.INPUT_TYPES  sJ     $ #CtL
  #CtL
 %0KH
 	
r%   rb   blurr   Nre   c                    UR                  5       S-  n/ nUb  Uc  Un[        U5      UR                  S5      :w  a)  [        S[        U5       SUR                  S5       35      e[	        UR                  S5      5       H(  n[        Xh   XH   XX   S4SS9n	UR                  U	5        M*     OA[	        UR                  S5      5       H#  n[        Xh   X#S4SS9n	UR                  U	5        M%     [        U5      4$ )Nrm   r   z3SigmasX must have same length as image, sigmasX is z but the batch size is r	   )sigmachannel_axis)rG  r:   r   ru   r}   r   r;   r   )
r>   re   rn  ro  rq  rr  image_npblurred_imagesr   blurreds
             r#   rt  MTB_Blur.blur  s    ;;=3&!7|uzz!}, I#g,Wnotoyoyz{o|n}~  5::a=)"K":wz15!"
 %%g. * 5::a=)"K': %%g.	 * .)++r%   r2   r   )rB   rC   rD   rE   r   rI   r5   rF   rG   rH   r   r   rt  rN   r2   r%   r#   rl  rl    sE    0
 
  LH%H JN,\\, ,r%   rl  c            
       f    \ rS rSrSr\S 5       rSrSrSr	S\
R                  S\S	\S
\S\4
S jrSrg)MTB_Sharpeni  z*Sharpens an image using a Gaussian kernel.c                 N    SSSSSSSS.4SSS	S
S	S.4SSS	S
S	S.4SSSSS	S.4S.0$ )Nr-   rb   r/   r      rZ   rU   rX   rR  g      $@rW   r   )re   sharpen_radiusr   r   alphar2   r3   s    r#   r5   MTB_Sharpen.INPUT_TYPES  so     # !!BB#
  #CcJ
  #CcJ
  #CSI
 	
r%   rb   do_sharpr   re   r  r   r   r  c                    US:X  a  U4$ UR                   S   nSU-  S-   n[        XsU5      US-  * -  nUS-  n	XU	4   UR                  5       -
  S-   XU	4'   UR                  USS5      R	                  S5      nUR                  SSSS5      n
[        R                  " U
X"X"4S5      n
[        R                  " XXS9nUS S 2S S 2X"* 2X"* 24   nUR                  SSSS5      n[        R                  " USS5      nU4$ )	Nr   rk   r	   r   
   rX   reflect)paddinggroups)rv   r$   r   repeatrx   r%  Fpadconv2dr   r   )r>   re   r  r   r   r  channelsr   kernelr   tensor_image	sharpenedr   s                r#   r  MTB_Sharpen.do_sharp;  s0    Q8O;;q>.(1, w?EBJ-O !!'!7&**,!F!Lv~xA.88;}}Q1a0uu^L

 HH&
	
 ?*?*,
	 %%aAq1	Y1-yr%   r2   N)rB   rC   rD   rE   r   rI   r5   rF   rG   rH   r   r   rL   r   r  rN   r2   r%   r#   r}  r}    sa    4
 
. LH%H+||+ + 	+
 + +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_MaskToImagei  zCConverts a mask (alpha) to an RGB image with a color and backgroundc                 2    SSSS04SSSS.4S.SS	S
S040S.$ )Nrc   COLOR
widgetType	MTB_COLORz#000000)r[   r  )rf   color
backgroundinvertr   r[   Frg   r2   r3   s    r#   r5   MTB_MaskToImage.INPUT_TYPES  sI     "!L+#>? )E 9y%&89
 	
r%   mtb/generaterb   render_maskc           
         U(       a  [        SU-
  5      O
[        U5      n/ nU H  nUR                  S5      n[        R                  " SUR                   35        [
        R                  " SUR                  US9n	[
        R                  " U	[
        R                  " SUR                  US9U5      n	UR                  U	R                  S5      5        M     [        U5      4$ )NrX   Lz*Converted mask to PIL Image format, size: RGBAr  r  )
r   r*   r
   debugr   r   new	compositer;   r   )
r>   rf   r  r  r  masksr  r/  _maskre   s
             r#   r  MTB_MaskToImage.render_mask  s    *0
3:&j6FAIIcNEII<UZZLI IIfejj>EOOuyy:FE MM%--./# & 6"$$r%   r2   N)F)rB   rC   rD   rE   r   rI   r5   rH   rF   rG   r  rN   r2   r%   r#   r  r    s-    M
 
 HLH%r%   r  c                      \ rS rSrSrSS jr\S 5       rSrSr	S	r
S
\R                  S\\\4   4S jrS
\R                  S\\\4   4S jr\S\R$                  S-  S\S\S\\R                     S-  4S j5       r    SS\S\S\S\R$                  S-  S\R$                  S-  S\S\S\\R$                     4S jjrSrg)MTB_ColoredImagei  z#Constant color image of given size.r7   Nc                     g r  r2   r>   s    r#   __init__MTB_ColoredImage.__init__  s    r%   c           	      J    SSSSSS.4SSSSS.4S.SS	S
SS04SSSSS.4S.S.$ )N)r  r/   i      i  )r[   r\   r9   )r  r   r   rb   rc   r   r[   FrU   rX   rR  r   )r[   r]   r\   )foreground_imageforeground_maskr  mask_opacityrg   r2   r3   s    r#   r5   MTB_ColoredImage.INPUT_TYPES  s`     $SD!IJ c"T"JK %/#,$y%&89 #S;!	
 	
r%   r  rb   
render_imgr  target_sizec                    [        US   UR                  -  US   UR                  -  5      n[        UR                  U-  5      [        UR                  U-  5      4nUR	                  U[
        R                  5      nUR                  US   -
  S-  nUR                  US   -
  S-  nUR                  XVXRS   -   XbS   -   45      $ )Nr   r   r	   )r9   r   r   rL   resizer   LANCZOScrop)r>   r  r  scalenew_sizelefttops          r#   resize_and_crop MTB_ColoredImage.resize_and_crop  s    KNSYY.A0KL		E)*C

U0B,CDjj5==1		KN*q0zzKN*q0xx1~-s^/CD
 	
r%   c                    UR                  U[        R                  5        UR                  US   -
  S-  nUR                  US   -
  S-  nUR                  US   -   S-  nUR                  US   -   S-  nUR                  X4XV45      $ )Nr   r	   r   )	thumbnailr   r  r   r   r  )r>   r  r  r  r  rightbottoms          r#   resize_and_crop_thumbnails+MTB_ColoredImage.resize_and_crop_thumbnails  s     	k5==1		KN*a/zzKN*a/[^+q0**{1~-2xxE233r%   rf   r  
batch_sizec                     U c  S /U-  $ [        U(       d  U OSU -
  5      n[        U5      S:X  a
  US:  a  X2-  n[        U5      U:w  a  [        S5      eU$ )NrX   r   z7Foreground image and mask must have the same batch size)r   r:   ru   )rf   r  r  r  s       r#   process_maskMTB_ColoredImage.process_mask  sd     <6J&&v43:>u:?zA~&Eu:#I  r%   r  r   r   r  r  r  c                 X   [         R                  " SX#4US9nUc  [        UR                  S5      /5      4$ [	        U5      n	U R                  XV[        U	5      5      n
/ n[        XSS9 GH2  u  pU R                  XR                  5      nU(       a  U R                  XR                  5      n[        R                  " U5      nX-  R                  [        R                  5      n[         R                  " U5      nUR                  [         R                   " UR                  S5      X5      R                  S5      5        M  UR"                  S:w  a  [%        SUR"                   35      eUR                  [         R&                  " X5      R                  S5      5        GM5     [        U5      4$ )Nr  r  r  F)strictzFForeground image must be in 'RGBA' mode when no mask is provided, got )r   r  r   r*   r   r  r:   zipr  r   nparrayastyper{   	fromarrayr;   r  r<  ru   alpha_composite)r>   r  r   r   r  r  r  r  r  	fg_imagesfg_masksr@   fg_imagefg_maskfg_mask_arrays                  r#   r  MTB_ColoredImage.render_img  sh    YYveD
#
 2 25 9:;==/0	$$_c)nM$&!$Y!GH++HooFH..wH " 1!.!= E Ebhh O//-8OO ((0*gen ==F*$`aianan`op  ))*?GGN' "H. 6"$$r%   r2   )r7   N)NNFrX   )rB   rC   rD   rE   r   r  rI   r5   rH   rF   rG   r   rK   rL   r  r  r   r   r   r   rJ   r  rM   r   r  rN   r2   r%   r#   r  r    s?   - 
 
$ HLH
5;; 
U38_ 
4;;4-238_4 llT! 	
 
ekk	T	! 4 15/3!*%*% *% 	*%
  ,,-*% ,*% *% *% 
u||	*% *%r%   r  c                   >    \ rS rSrSr\S 5       rSrSrSr	Sr
S rS	rg
)MTB_ImagePremultiplyi,  zPremultiply image with maskc                     SSSSSS04S.0$ )Nr-   rb   rc   r   r[   F)re   rf   r  r2   r3   s    r#   r5    MTB_ImagePremultiply.INPUT_TYPES/  s)     #!$y%&89
 	
r%   r?  rb   )r  premultiplyc                 f   [        U5      nU(       a  [        U5      O[        SU-
  5      n[        U5      S:H  nU Vs/ s H  owR                  S5      PM     nn/ n[        U5       H7  u  pU(       a  US   OXY   nU
R	                  U5        UR                  U
5        M9     [        U5      4$ s  snf )NrX   r   r  r   )r   r:   r*   	enumerateputalphar;   r   )r>   re   rf   r  r  r  singler   r  r   r  cur_masks               r#   r   MTB_ImagePremultiply.premultiply>  s    E"$*
4 
3:0FTa)./A3/'FA#)uQxuxHLL"JJsO	 ( 3!! 0s   B.r2   N)rB   rC   rD   rE   r   rI   r5   rH   rF   RETURN_NAMESrG   r  rN   r2   r%   r#   r  r  ,  s2    %
 
 HLLH"r%   r  c            	       h    \ rS rSrSr\S 5       rSrSrSr	 SS\
R                  S	\S
\S\4S jjrSrg)MTB_ImageResizeFactoriS  zoExtracted mostly from WAS Node Suite, with a few edits (most notably multiple image support) and less features.c                 <    SSSSSSS.4SSS	04/ S
QSS04S.SS0S.$ )Nrb   rU   r	   rY   g      0@rZ   r   r[   T)nearestlinearbilinearbicubic	trilinearareaznearest-exactr  )re   factorsupersample
resamplingrf   rc   rg   r2   r3   s    r#   r5   !MTB_ImageResizeFactor.INPUT_TYPESV  sY     $ !$tTJ !*It+<= 	** 	+
 	
r%   r?  )rR   rd   r  Nre   r  r  r  c                    [        UR                  5      S;  a  [        S5      e[        UR                  5      S:X  a#  UR                  SSS5      R	                  S5      nOUR                  SSSS5      nUR                  u  pgp[        X-  5      [        X-  5      pSn[        R                  " UX4UXL;   S9nU(       a  [        R                  " USUXL;   S	9n[        UR                  5      S
:X  a  UR                  SSSS5      nO"UR                  S5      R                  SSS5      nUb;  [        UR                  5      [        UR                  5      :w  a  [        S5      eX-  nU4$ )N)rk   rn   z8Expected image tensor of shape (H, W, C) or (B, H, W, C)rk   r	   r   r   )r  r  r  r  )r   r<  align_corners)scale_factorr<  r  rn   z?Mask tensor should have the same dimensions as the image tensor)	r:   rv   ru   r%  rx   rL   r  interpolater$  )r>   re   r  r  r  rf   BCHWnew_Hnew_Walign_corner_filtersresized_images                 r#   r  MTB_ImageResizeFactor.resizev  s`    u{{6)J 
 u{{q MM!Q*44Q7EMM!Q1-E [[
a1:AJuM$<	
 MM(@	M u{{q )11!Q1=M)11!4<<Q1EM 4::#m&9&9":: U  *0Mr%   r2   r  )rB   rC   rD   rE   r   rI   r5   rH   rF   rG   r   r   r   r   rM   r  rN   r2   r%   r#   r  r  S  sa    y
 
6 H$LH 8 ||8  8  	8 
 8  8 r%   r  c                   V    \ rS rSrSrS r\S 5       rSrSr	Sr
SrS	 r    SS jrSrg
)MTB_SaveImageGridi  z;Save all the images in the input batch as a grid of images.c                 F    [         R                  " 5       U l        SU l        g )Nr@   )folder_pathsget_output_directory
output_dirtyper  s    r#   r  MTB_SaveImageGrid.__init__  s    &;;=	r%   c                 *    SSSS04SSS04S.SS	S
.S.$ )Nrb   r)   r[   ComfyUIr   F)r  filename_prefixsave_intermediatePROMPTEXTRA_PNGINFO)promptextra_pnginfo)r-   hiddenr2   r3   s    r#   r5   MTB_SaveImageGrid.INPUT_TYPES  s:     %$,y).D#E&/)U1C%D
 "*OL
 	
r%   r2   save_imagesTrX  c           	         [        U5      n[        [        R                  " U5      5      [        [        R                  " [        R                  " U5      5      5      4nUS   R
                  u  pEUS   U-  nUS   U-  n[        R                  " SXg45      n[        U5       H2  u  pXS   -  U-  nXS   -  U-  nUR                  XXU-   X-   45        M4     U$ )Nr   r   r  )
r:   rL   mathsqrtceilr   r   r  r  paste)r>   
image_listtotal_images	grid_sizeimage_widthimage_height
grid_widthgrid_height
grid_imager   re   r   r   s                r#   create_image_grid#MTB_SaveImageGrid.create_image_grid  s    : 		,'(		$))L123
	 %/qM$6$6! q\K/
l\1YYuz&?@
 "*-HAq\![0Al"l2AU{?A<L$MN .
 r%   Nc                    [         R                  " UU R                  US   R                  S   US   R                  S   5      u  nnnn	n/ n
Un[	        5       nUb&  UR                  S[        R                  " U5      5        Ub1  U H+  nUR                  U[        R                  " X]   5      5        M-     [        U5       H  u  pSUR                  5       R                  5       -  n[        R                  " [        R                  " USS5      R                  [        R                   5      5      nU
R#                  U5        U(       a<  U SUS SUS	 S
3nUR%                  [&        R(                  R+                  UU5      USS9  US-  nM     U SUS	 S
3nU R-                  U
5      nUR%                  [&        R(                  R+                  UU5      USS9  UXR.                  S./nSSU00$ )Nr   r   r  g     o@rm   z_batch-03r   05z_.pngrn   )pnginfocompress_level)filename	subfolderr  uir  )r  get_save_image_pathr  rv   r   add_textr<   r=   r  r   rG  r   r  r  clipr  r{   r;   saveospathjoinr  r  )r>   r  r  r	  r  r  full_output_folderr%  counterr&  r  batch_countermetadatar   idxre   r   r  filegridresultss                        r#   r  MTB_SaveImageGrid.save_images  s    ,,OO1IOOA1IOOA	
	
 
9h

6(:;$"!!!TZZ0@%AB # $F+JC		))++A//"''!Q"4";";BHH"EFCc" "73r(!M"3EUKGGLL!3T:$#$   QM , 1WRL.%%j1		GGLL+T2 	 	
 IyyI
 x)**r%   )r  r  )GridFNN)rB   rC   rD   rE   r   r  rI   r5   rF   rG   OUTPUT_NODErH   r  r  rN   r2   r%   r#   r  r    sL    E 
 
 LHKH8 8+r%   r  c                   d    \ rS rSrSr\S 5       rSrSrSr	 SS\
R                  S\S	\4S
 jjrSrg)MTB_ImageTileOffseti  z@Mimics an old photoshop technique to check for seamless texturesc                 &    SSSSSS.4SSSS.4S.0$ )Nr-   rb   r/   r	   r   r_   )re   tilesXtilesYr2   r3   s    r#   r5   MTB_ImageTileOffset.INPUT_TYPES!  s3     # a":; a":;
 	
r%   r  rb   
tile_imagere   r=  r>  c                    US:  d  US:  a  [        S5      eUR                  u  pEpgXS-  nXb-  n	[        R                  " U5      n
[        R
                  " [        U5      [        U5      5       HV  u  pX-  nX-   nX-  nX-   nUS S 2X2UU2S S 24   nUS-   U-  U-  nUS-   U-  U	-  nUU-   nUU	-   nUU
S S 2UU2UU2S S 24'   MX     U
4$ )Nr   z'The number of tiles must be at least 1.)ru   rv   r   r&  	itertoolsproductr}   )r>   re   r=  r>  r  r   r   r  tile_height
tile_widthoutput_imager   jstart_hend_hstart_wend_wtileoutput_start_houtput_start_woutput_end_houtput_end_ws                         r#   r@  MTB_ImageTileOffset.tile_image1  s    A:!FGG.3kk+
E&_
''.%%eFmU6]CDAoG)EnG(EGM75=!;<D!ev-;N!ev-
:N)K7L)J6L  >,.|0KQN D" r%   r2   N)r	   r	   )rB   rC   rD   rE   r   rI   r5   rH   rF   rG   r   r   rL   r@  rN   r2   r%   r#   r;  r;    sU    J
 
 HLH CD\\+.<? r%   r;  r  )1rB  r<   r  r,  comfy.utilscomfyr  rG  r  r   torch.nn.functionalnn
functionalr  r   PILr   r   PIL.PngImagePluginr   skimage.filtersr   skimage.utilr   r
   utilsr   r   r   rL   r   r$   r'   rP   r   r   r6  r[  rb  rO  rl  r}  r  r  r  r  r  r;  	__nodes__r2   r%   r#   <module>r]     sD      	       "  & $ '  5 5 >B$/4% %6P1 P1fW Wtr rjE  E P  0W 0Wf5, 5,pJ JN0% 0%fs% s%l$" $"N[  [ |j+ j+Z0 0h #	r%   