
    
3j2                     T   S SK r S SKrS SKJ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\S	\S
\S\S\\\4   4S jrS\\   S\S\\\\4      4S jr\" SSS9 " S S\R&                  5      5       rS\S\\\      4S jrS\R,                  S\R.                  S\R,                  4S jrS\S\S\4S jrSrSrS rS!r\" S"S#S9 " S$ S"\R&                  5      5       rS%\R,                  S&\R,                  S'\R,                  S(\R,                  S)\R,                  S*\S+\S,\S-\SS4S. jrg)/    N)BytesIO)io)Image   )
comfy_nodep0p1p2p3treturnc                    XD-  nXT-  nSSUS   -  U S   * US   -   U-  -   SU S   -  SUS   -  -
  SUS   -  -   US   -
  U-  -   U S   * SUS   -  -   SUS   -  -
  US   -   U-  -   -  SSUS   -  U S   * US   -   U-  -   SU S   -  SUS   -  -
  SUS   -  -   US   -
  U-  -   U S   * SUS   -  -   SUS   -  -
  US   -   U-  -   -  S.$ )	Ng      ?   x         yr   r    )r   r	   r
   r   r   t2t3s          K/home/wildlama/comfy/ComfyUI/custom_nodes/ComfyUI-LTXVideo/sparse_tracks.py_catmull_romr      s^   	
B	B3K3x"S'!Q&'2c7{QC[(1r#w;6C@BFG 3x!bg+%BsG3bg=CD
 3K3x"S'!Q&'2c7{QC[(1r#w;6C@BFG 3x!bg+%BsG3bg=CD
     control_pointsnum_samplesc           
         [        U 5      S:X  a  / $ [        U 5      S:X  a<  U S   n[        U5       Vs/ s H   n[        US   5      [        US   5      S.PM"     sn$ [        U 5      S:X  ae  U u  pE[        U5       Vs/ s HJ  n[        US   US   US   -
  U-  US-
  -  -   5      [        US   US   US   -
  U-  US-
  -  -   5      S.PML     sn$ U S   /U QU S   Pn[        U5      S-
  n/ n	[        U5       Hu  nXaS-
  -  U-  n
[        [	        U
5      US-
  5      nX-
  n[        X{   X{S-      X{S-      X{S-      U5      nU	R                  [        US   5      [        US   5      S.5        Mw     U	$ s  snf s  snf )	z@Catmull-Rom spline interpolation matching the JS frontend logic.r   r   r   r   r   r   r   )lenrangeroundminintr   append)r   r   p_abiptsn_segresultg_tsegl_ts                r   _interpolate_spliner1   "   s    >a	
>a1BGBTUBTQeAcFm%#-8BTUU
>a ;'

 ( 1S6QsVaf_$9[1_$MMN1S6QsVaf_$9[1_$MMN (
 	
 !
B~
B~b/A
BCHqLEF;!O$-#c(EAI&i3Qw<1Ws7|SQE!C&Maf>?   M' V
s   'E4=AE9LTXVSparseTrackEditorzLTX Sparse Track Editor)namedescriptionc            	       `    \ rS rSrSr\S 5       r\S\S\S\S\	R                  4S j5       rS	rg
)r2   @   zInteractive spline editor for drawing sparse motion tracks.

Provides a canvas widget where users can draw and edit spline control
points on top of a reference image. Outputs interpolated track
coordinates compatible with LTXVDrawTracks.
c                 b   [         R                  " SSS[         R                  R                  SSS9[         R                  R                  SSS	S
9[         R                  R                  SSSS
9[         R
                  R                  SSSSSS9/[         R                  R                  S5      /SS9$ )Nr2   Lightricks/motion_trackingzPInteractive spline editor for drawing sparse motion tracks on a reference image.imagez:Reference image displayed as the editor canvas background.)tooltippoints_store[]zAJSON array of spline control points managed by the editor widget.)defaultr:   coordinateszDJSON array of interpolated track coordinates produced by the editor.points_to_sampley   r   i'  z1Number of points sampled along each spline curve.)r=   r#   maxr:   tracksT)node_idcategoryr4   inputsoutputsis_output_node)r   Schemar   InputStringIntOutputclss    r   define_schema#LTXVSparseTrackEditor.define_schemaI   s    yy+1( X   		" _   
 		! b   
 &O  0 		  *  C"
 "	
r   r;   r>   r?   r   c                     U(       a  [         R                  " U5      O/ nU(       a_  [	        U[
        5      (       aJ  [	        US   [
        5      (       a2  U Vs/ s H  n[        Xd5      PM     nn[         R                  " U5      nOU(       a	  US:w  a  UnOSnUS   R                  5       R                  5       S-  R                  [        R                  5      n	[        R                  " U	5      n
[        5       nU
R!                  USSS9  ["        R$                  " UR'                  5       5      R)                  S5      n[*        R,                  " USU/0S	9$ ! [         R                  [        4 a    / n GNTf = fs  snf )
Nr   r<      JPEGK   )formatqualityzutf-8bg_image)ui)jsonloadsJSONDecodeError	TypeError
isinstancelistr1   dumpscpunumpyastypenpuint8r   	fromarrayr   savebase64	b64encodegetvaluedecoder   
NodeOutput)rN   r9   r;   r>   r?   splinesspinterpolatedrB   	img_arrayimgbufimg_b64s                r   executeLTXVSparseTrackEditor.executeo   s*   	2>djj.BG z'400Z
D5Q5QPWXPW"/EPWLXZZ-F[D0 FF1X\\^))+c199"((C	ooi(iVR0""3<<>299'B}}VgY(?@@! $$i0 	G	 Ys   E E9E65E6r   N__name__
__module____qualname____firstlineno____doc__classmethodrO   strr$   r   rk   rs   __static_attributes__r   r   r   r2   r2   @   sb     #
 #
J A A 	A
 A 
A Ar   rawc                 H   [        U [        5      (       a  [        R                  " U 5      OU n[        U[        5      (       aI  / nU H?  nUR                  [        U[        5      (       a  [        R                  " U5      OU5        MA     Un/ nU/nU(       a  UR                  5       n[        U[        5      (       a\  [        U5      S:  aM  [        US   [        5      (       a$  SUS   ;   a  SUS   ;   a  UR                  U5        OUR                  U5        U(       a  M  U$ )zAParse tracks from a JSON string, handling nested/wrapped formats.r   r   r   )
r]   r|   rY   rZ   r^   r%   popr    dictextend)r~   parsed	unwrappeditemrB   stackobjs          r   _parse_tracksr      s     *3 4 4TZZ_#F&$	DD#1F1FTZZ-DQ !FHE
iikc4  SX\#a&$''C3q6McSVmc"S! % Mr   ratiosdevicec                     [         R                  " U R                  S   SUS9nU S:*  nX   S-  nXBUS4'   SU-
  X#S4'   U S:  U S:*  -  nX   S-
  S-  nXbUS4'   SX%S4'   U S:  nX   S-
  S-  nSX'S4'   SU-
  X'S4'   U$ )z^Vectorised age-ratio -> RGB [0..1] mapping on GPU.

Gradient: blue -> green -> yellow -> red.
r   r   r   gUUUUUU?r   r   gUUUUUU?)torchzerosshape)	r   r   colorsm1tr1m2tr2m3tr3s	            r   _age_color_batchr      s    
 [[a!F;F	5B
*q.C2q5MGFq5M
5.Vu_	-B:
"C2q5MFq5M	%B:
"CFq5MGFq5MMr   widthheightreference_short_sidec                 n    X::  a  [        X-  U-  5      nUnOUn[        X-  U -  5      nX0-  nXA-  nX4XV4$ )zACompute the higher render resolution that preserves aspect ratio.)r$   )r   r   r   rwrhscale_xscale_ys          r   _render_resolutionr      sN    -67!!.67jGkG7##r   r      2   i8  LTXVDrawTrackszLTX Draw Sparse Tracksc            	       `    \ rS rSrSr\S 5       r\S\S\S\S\	R                  4S j5       rS	rg
)r      u   GPU-accelerated sparse track renderer.

Renders circles at a high reference resolution and downscales with
bilinear interpolation so circle sizes match the CPU version.
All work — rasterisation, compositing and resize — stays on GPU.
c                 ,   [         R                  " SSS[         R                  R                  SSSS9[         R                  R                  SS	S
SS
SS9[         R                  R                  SS	S
SS
SS9/[         R
                  R                  5       /S9$ )Nr   r8   zxGPU-accelerated sparse track renderer. Rasterises circles at high resolution and downscales with bilinear interpolation.rB   TzEJSON string of track coordinates (list of point lists with x/y keys).)	multiliner:   r   i   r   i    zOutput image width in pixels.)r=   r#   rA   stepr:   r   zOutput image height in pixels.)rC   rD   r4   rE   rF   )r   rH   rJ   rI   rK   r   rL   rM   s    r   rO   LTXVDrawTracks.define_schema   s    yy$1N 		"c   
 ;   <  0 !=!
 !	
r   rB   r   r   r   c                    [         R                  " [         R                  R                  5       (       a  SOS5      n[	        U5      nU(       d<  [         R
                  " SX2SU[         R                  S9n[        R                  " U5      $ [        U5      n[        S U 5       5      n[        X#[        5      u  pp[         R
                  " XxSUS9n[         R
                  " Xx[         R                  US	9n[        U5       Hk  u  nn[         R                  " U Vs/ s H  nUS
   U-  US   U-  /PM     sn[         R                   US	9nUXS [        U5      24'   SXS [        U5      24'   Mm     S["        -  S-   nUS-  n[         R$                  " UUS9U-
  n[         R&                  " UUSS9u  nnUR)                  5       R+                  5       UR)                  5       R+                  5       -   n[         R
                  " XU	SUS9n[-        U5       GH  n[        SU[.        -
  5      nUU-
  S-   nUS S 2UUS-   24   nUS S 2UUS-   24   n[         R$                  " US-
  SSU[         R                   S9nSU[.        -  -
  n [0        ["        [0        -
  U -  -   n![3        U U5      n"UR5                  SS5      n#UR5                  S5      n$U!R7                  S5      R9                  US5      R5                  S5      n%U"R7                  S5      R9                  USS5      R5                  SS5      n&U$R;                  SS9S   n'U'R<                  S   S:X  a  GM@  U#U'   n(U%U'   n)U&U'   n*UR7                  S5      R9                  US5      R5                  S5      n+U+U'   R?                  SS9n,U(U,   n(U)U,   n)U*U,   n*[A        UU   U(U)U*UUUX5	        GM     [         RB                  RD                  RG                  URI                  SSSS5      X24SSS9RI                  SSSS5      n-U-S/ SQ4   n-[        R                  " U-R                  5       5      $ s  snf )Ncudar`   r   r   r   dtypec              3   8   #    U  H  n[        U5      v   M     g 7f)N)r    ).0r   s     r   	<genexpr>)LTXVDrawTracks.execute.<locals>.<genexpr>  s     0AQs   r   r   )r   r   r   r   Tij)indexingr   r   g      ?)as_tuple)
descendingbilinearF)sizemodealign_corners.)r   r   r   )%r   r   r   is_availabler   r   halfr   rk   r    rA   r   _REF_SHORT_SIDEbool	enumeratetensorfloat32_MAX_RADIUSarangemeshgridfloatsquarer!   
_MAX_TRAIL_MIN_RADIUSr   reshape	unsqueezeexpandnonzeror   argsort_rasterise_circlesnn
functionalinterpolatepermute).rN   rB   r   r   r   r   blank
num_tracks
num_framesr   r   sxsypoint_xyvisr*   trkr&   coordsmax_dhalf_doffsetsoyoxtemplate_dist_sqrender_framesr   tau_minwindow	active_xy
active_visagesr   radiir   flat_xyflat_vis
flat_radiiflat_colorsidxr+   rc	flat_ages
sort_orderouts.                                                 r   rs   LTXVDrawTracks.execute   s   

(?(?(A(AfuMv&KK6!F%**UE==''[
000
+E?K;;zqHkk*

6R'FAs\\589S!C&2+qv{+S9mmF
 '-H
#c(
]#!%C:SX: ( K!#!,,uV4v=4@B88:,,.1B1B1DDJB&Iz"A!Q^,G[1_F Ga!eO!34IQ!a%/0J<<
B6WD4*,,F;#<"FFE%ff5F''A.G!))"-H+22:rBJJ2NJ **1-44ZRHPPQSUVWK""D"1!4Cyy|q #,C3AC Aq)00R@HHLI"3//4/@Jj/C*A*Aa #q!-=vub? #F hh!!--!!!Q1-	 . 

 '!Q1
 	 #y.!}}SXXZ((u :s   Q
r   Nru   r   r   r   r   r      sV     "
 "
H H)S H) H)c H)bmm H) H)r   framer+   r   r   r   r   r   HWc	                 R   UR                   S   n	U	S:X  a  gUR                  n
X"-  R                  U	SS5      nUR                  S5      U:*  nUSS2S4   R	                  5       R                  5       R                  U	SS5      nUSS2S4   R	                  5       R                  5       R                  U	SS5      n[        R                  " XjS9R                  U5      R                  SUS5      n[        R                  " XjS9R                  U5      R                  SSU5      nX-   R                  XU5      nUU-   R                  XU5      nUUS:  -  UU:  -  US:  -  UU:  -  nUU   nUU   nUU-  U-   R                  5       n[        R                  " X[        R                  S9R                  U	SS5      nUR                  U5      nUU   n[        R                  " Xx-  4SU
S9nUR                  SUUSSS	9  UR                  Xx5      R                  5       nUS:  nUUU      U U'   g)
zStamp filled circles onto *frame* fully on-device.

Uses ``scatter_reduce_`` with ``'amax'`` to resolve overlaps in
painter's order (circles are expected oldest-first so the highest
index = newest wins).
r   Nr   r   r   g      amaxF)reduceinclude_self)r   r   viewr   r"   longr   r   subr   r   	expand_asfullscatter_reduce_)r   r+   r   r   r   r   r   r   r   Mr   radii_sqcircle_maskscxcy	offsets_y	offsets_xfyfxvalidflat_fyflat_fxflat_linj_mapflat_jpriority
has_circles                              r   r   r   J  s   " 			!AAvZZF ##Aq!,H#--a0H<L 
QT				!	&	&q!Q	/B	QT				!	&	&q!Q	/BU266v>CCAuaPIU266v>CCAq%PI
.	 	 5	1B
y.	 	 5	1BB!G$Q/27;rAvFEiGiG!g%++-H LL?DDQ1MEOOE"E5\F zz15(D8HQ&eT}}Q"'')HQJx
34E*r   ) rg   rY   r   r   ra   rc   r   comfy_api.latestPILr   nodes_registryr   r   r   r|   r   r^   r$   r1   	ComfyNoder2   r   Tensorr   r   r   r   r   r   r   r   r   r   r   r   <module>r     s          &T t  4 E d3PU:FV *J-0	$sCx.< (6OPJABLL JA QJAZs tDJ/ ,U\\ 5<< ELL 2
$c 
$3 
$c 
$ 
 !/GHv)R\\ v) Iv)r35<<35	35 <<35 LL	35
 ll35 35 35 35 35 
35r   