Skip to content

Commit a51a03a

Browse files
authored
Merge pull request AUTOMATIC1111#9 from jtydhr88/add-send-to-cleaner-buttons-2
add send to cleaner buttons
2 parents 01ea3ca + 013c97f commit a51a03a

File tree

2 files changed

+294
-2
lines changed

2 files changed

+294
-2
lines changed

javascript/cleaner.js

+292
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,296 @@
88
}
99
}
1010
});
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+
});
11303
})();

scripts/clean_up_tab.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ def on_ui_tabs():
4343
else:
4444
with gr.Column(elem_id=f"cleanup_image_mask"):
4545
clean_up_init_img = gr.Image(label="Image for cleanup", show_label=False, source="upload",
46-
interactive=True, type="pil", elem_id="img_inpaint_base", height=325)
46+
interactive=True, type="pil", elem_id="cleanup_img_inpaint_base", height=325)
4747
clean_up_init_mask = gr.Image(
48-
label="Mask", source="upload", interactive=True, type="pil", image_mode="RGBA", elem_id="img_inpaint_mask", height=325)
48+
label="Mask", source="upload", interactive=True, type="pil", image_mode="RGBA", elem_id="cleanup_img_inpaint_mask", height=325)
4949

5050
with gr.Row():
5151

0 commit comments

Comments
 (0)