8
8
}
9
9
}
10
10
} ) ;
11
+
12
+ onUiLoaded ( function ( ) {
13
+ createSendToCleanerButtonSegmentAnything ( "txt2img_script_container" ) ;
14
+
15
+ createSendToCleanerButton ( "image_buttons_txt2img" , window . txt2img_gallery ) ;
16
+ createSendToCleanerButton ( "image_buttons_img2img" , window . img2img_gallery ) ;
17
+ createSendToCleanerButton ( "image_buttons_extras" , window . extras_gallery ) ;
18
+
19
+ function createSendToCleanerButtonSegmentAnything ( queryId ) {
20
+ let container = gradioApp ( ) . querySelector ( `#${ queryId } ` ) ;
21
+
22
+ if ( ! container ) {
23
+ return ;
24
+ }
25
+
26
+ let spans = container . getElementsByTagName ( 'span' ) ;
27
+ let targetSpan = null ;
28
+
29
+ for ( let span of spans ) {
30
+ if ( span . textContent . trim ( ) === 'Segment Anything' ) {
31
+ targetSpan = span ;
32
+ break ;
33
+ }
34
+ }
35
+
36
+ if ( ! targetSpan ) {
37
+ return ;
38
+ }
39
+
40
+ let parentDiv = targetSpan . parentElement ;
41
+ let segmentAnythingDiv = parentDiv . nextElementSibling ;
42
+
43
+ if ( segmentAnythingDiv && segmentAnythingDiv . tagName === 'DIV' ) {
44
+ let tabsDiv = segmentAnythingDiv . querySelector ( '.tabs' ) ;
45
+
46
+ if ( tabsDiv ) {
47
+ let grandchildren = [ ] ;
48
+
49
+ for ( let child of tabsDiv . children ) {
50
+ grandchildren . push ( ...child . children ) ;
51
+ }
52
+
53
+ let targetButton = grandchildren [ grandchildren . length - 1 ] ;
54
+
55
+ if ( targetButton && targetButton . tagName === 'BUTTON' ) {
56
+ const newButton = targetButton . cloneNode ( true ) ;
57
+
58
+ newButton . title = "Send mask to Cleaner"
59
+ newButton . textContent = "Send mask to Cleaner" ;
60
+ newButton . addEventListener ( "click" , ( ) => sendSegmentAnythingSourceMask ( segmentAnythingDiv ) ) ;
61
+
62
+ targetButton . parentNode . appendChild ( newButton ) ;
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ function getSegmentAnythingMask ( container ) {
69
+ let chooseIndex = getChooseMaskIndex ( container ) ;
70
+
71
+ let maskGridDiv = container . querySelector ( ".grid-container" ) ;
72
+
73
+ let chooseMaskButton = maskGridDiv . children [ chooseIndex + 3 ] ;
74
+
75
+ let chooseMaskImg = chooseMaskButton . querySelector ( "img" ) ;
76
+
77
+ let chooseMaskImgSrc = chooseMaskImg . src ;
78
+
79
+ let targetExpandMaskSpan = findSpanNode ( container , "Expand Mask" ) ;
80
+
81
+ if ( targetExpandMaskSpan ) {
82
+ let checkbox = targetExpandMaskSpan . parentNode . children [ 0 ] ;
83
+
84
+ if ( checkbox . checked ) {
85
+ let targetExpandMaskInfoSpan = findSpanNode ( container , "Specify the amount that you wish to expand the mask by (recommend 30)" ) ;
86
+
87
+ let parentDiv = targetExpandMaskInfoSpan . parentNode . parentNode . parentNode . parentNode . parentNode ;
88
+
89
+ let expandMaskDiv = parentDiv . nextElementSibling ;
90
+
91
+ let gridContainer = expandMaskDiv . querySelector ( ".grid-container" ) ;
92
+
93
+ if ( gridContainer ) {
94
+ let expandMaskButton = gridContainer . children [ 1 ] ;
95
+
96
+ let expandMaskImg = expandMaskButton . querySelector ( "img" ) ;
97
+
98
+ chooseMaskImgSrc = expandMaskImg . src ;
99
+ }
100
+ }
101
+ }
102
+
103
+ return chooseMaskImgSrc ;
104
+ }
105
+
106
+ function sendSegmentAnythingSourceMask ( container ) {
107
+ let inputImg = container . querySelector ( '#txt2img_sam_input_image div[data-testid="image"] img' ) ;
108
+
109
+ let inputImgSrc = inputImg . src ;
110
+
111
+ let chooseMaskImgSrc = getSegmentAnythingMask ( container ) ;
112
+
113
+ switchToCleanerTag ( true ) ;
114
+
115
+ fetch ( chooseMaskImgSrc )
116
+ . then ( response => response . blob ( ) )
117
+ . then ( blob => {
118
+ let maskContainer = gradioApp ( ) . querySelector ( "#cleanup_img_inpaint_mask" ) ;
119
+
120
+ const imageElems = maskContainer . querySelectorAll ( 'div[data-testid="image"]' )
121
+
122
+ if ( imageElems ) {
123
+ const dt = new DataTransfer ( ) ;
124
+ dt . items . add ( new File ( [ blob ] , "maskImage.png" ) ) ;
125
+ updateGradioImage ( imageElems [ 0 ] , dt ) ;
126
+ }
127
+ } )
128
+ . catch ( error => {
129
+ console . error ( "Error fetching image:" , error ) ;
130
+ } ) ;
131
+
132
+ let cleanupContainer = gradioApp ( ) . querySelector ( "#cleanup_img_inpaint_base" ) ;
133
+
134
+ const imageElems = cleanupContainer . querySelectorAll ( 'div[data-testid="image"]' )
135
+
136
+ if ( imageElems ) {
137
+ const dt = new DataTransfer ( ) ;
138
+ dt . items . add ( dataURLtoFile ( inputImgSrc , "segmentAnythingInput.png" ) ) ;
139
+ updateGradioImage ( imageElems [ 0 ] , dt ) ;
140
+ }
141
+ }
142
+
143
+ function getChooseMaskIndex ( container ) {
144
+ let chooseMaskSpans = container . getElementsByTagName ( 'span' ) ;
145
+
146
+ let targetChooseMaskSpan = null ;
147
+
148
+ for ( let span of chooseMaskSpans ) {
149
+ if ( span . textContent . trim ( ) === 'Choose your favorite mask:' ) {
150
+ targetChooseMaskSpan = span ;
151
+ break ;
152
+ }
153
+ }
154
+
155
+ let selectedIndex = - 1 ;
156
+
157
+ if ( targetChooseMaskSpan ) {
158
+ let chooseMaskIndexDiv = targetChooseMaskSpan . nextElementSibling ;
159
+
160
+ let labels = chooseMaskIndexDiv . children ;
161
+
162
+ for ( let i = 0 ; i < labels . length ; i ++ ) {
163
+ if ( labels [ i ] . classList . contains ( 'selected' ) ) {
164
+ selectedIndex = i ;
165
+ break ;
166
+ }
167
+ }
168
+ }
169
+
170
+ return selectedIndex ;
171
+ }
172
+
173
+ function createSendToCleanerButton ( queryId , gallery ) {
174
+ const existingButton = gradioApp ( ) . querySelector ( `#${ queryId } button` ) ;
175
+ const newButton = existingButton . cloneNode ( true ) ;
176
+
177
+ newButton . style . display = "flex" ;
178
+ newButton . id = `${ queryId } _send_to_cleaner` ;
179
+ newButton . addEventListener ( "click" , ( ) => sendImageToCleaner ( gallery ) ) ;
180
+ newButton . title = "Send to Cleaner"
181
+ newButton . textContent = "\u{1F9F9}" ;
182
+
183
+ existingButton . parentNode . appendChild ( newButton ) ;
184
+ }
185
+
186
+ function switchToCleanerTag ( cleanupMaskTag ) {
187
+ const tabIndex = getCleanerTabIndex ( ) ;
188
+
189
+ gradioApp ( ) . querySelector ( '#tabs' ) . querySelectorAll ( 'button' ) [ tabIndex - 1 ] . click ( ) ;
190
+
191
+ if ( cleanupMaskTag ) {
192
+ let buttons = gradioApp ( ) . querySelectorAll ( `#tab_cleaner_tab button` ) ;
193
+
194
+ let targetButton = null ;
195
+
196
+ for ( let button of buttons ) {
197
+ if ( button . textContent . trim ( ) === 'Clean up upload' ) {
198
+ targetButton = button ;
199
+ break ;
200
+ }
201
+ }
202
+
203
+ if ( targetButton ) {
204
+ targetButton . click ( ) ;
205
+ }
206
+ }
207
+ }
208
+
209
+ function sendImageToCleaner ( gallery ) {
210
+ const img = gallery . querySelector ( ".preview img" ) ;
211
+
212
+ if ( img ) {
213
+ const imgUrl = img . src ;
214
+
215
+ switchToCleanerTag ( false ) ;
216
+
217
+ fetch ( imgUrl )
218
+ . then ( response => response . blob ( ) )
219
+ . then ( blob => {
220
+ let container = gradioApp ( ) . querySelector ( "#cleanup_img2maskimg" ) ;
221
+
222
+ const imageElems = container . querySelectorAll ( 'div[data-testid="image"]' )
223
+
224
+ if ( imageElems ) {
225
+ const dt = new DataTransfer ( ) ;
226
+ dt . items . add ( new File ( [ blob ] , "image.png" ) ) ;
227
+ updateGradioImage ( imageElems [ 0 ] , dt ) ;
228
+ }
229
+ } )
230
+ . catch ( error => {
231
+ console . error ( "Error fetching image:" , error ) ;
232
+ } ) ;
233
+ } else {
234
+ alert ( "No image selected" ) ;
235
+ }
236
+ }
237
+
238
+ function updateGradioImage ( element , dt ) {
239
+ let clearButton = element . querySelector ( "button[aria-label='Remove Image']" ) ;
240
+
241
+ if ( clearButton ) {
242
+ clearButton . click ( ) ;
243
+ }
244
+
245
+ const input = element . querySelector ( "input[type='file']" ) ;
246
+
247
+ input . value = '' ;
248
+ input . files = dt . files ;
249
+
250
+ input . dispatchEvent (
251
+ new Event ( 'change' , {
252
+ bubbles : true ,
253
+ composed : true ,
254
+ } )
255
+ )
256
+ }
257
+
258
+ function dataURLtoFile ( dataurl , filename ) {
259
+ var arr = dataurl . split ( ',' ) ,
260
+ mime = arr [ 0 ] . match ( / : ( .* ?) ; / ) [ 1 ] ,
261
+ bstr = atob ( arr [ 1 ] ) ,
262
+ n = bstr . length ,
263
+ u8arr = new Uint8Array ( n ) ;
264
+
265
+ while ( n -- ) {
266
+ u8arr [ n ] = bstr . charCodeAt ( n ) ;
267
+ }
268
+
269
+ return new File ( [ u8arr ] , filename , { type : mime } ) ;
270
+ }
271
+
272
+ function findSpanNode ( container , text ) {
273
+ let spans = container . querySelectorAll ( "span" ) ;
274
+
275
+ let targetSpan = null ;
276
+
277
+ for ( let span of spans ) {
278
+ if ( span . textContent . trim ( ) === text ) {
279
+ targetSpan = span ;
280
+ break ;
281
+ }
282
+ }
283
+
284
+ return targetSpan ;
285
+ }
286
+
287
+ function getCleanerTabIndex ( ) {
288
+ const tabCanvasEditorDiv = document . getElementById ( 'tab_cleaner_tab' ) ;
289
+ const parent = tabCanvasEditorDiv . parentNode ;
290
+ const siblings = parent . childNodes ;
291
+
292
+ let index = - 1 ;
293
+ for ( let i = 0 ; i < siblings . length ; i ++ ) {
294
+ if ( siblings [ i ] === tabCanvasEditorDiv ) {
295
+ index = i ;
296
+ break ;
297
+ }
298
+ }
299
+
300
+ return index / 3 ;
301
+ }
302
+ } ) ;
11
303
} ) ( ) ;
0 commit comments