extensions / sd-webui-controlnet /javascript /img2img_input_display.js
방재호
init
b5ba7a5
/**
* Display the currently active img2img tab's input image as an uninteractable
* background image behind ControlNet's image input. This change will hint user
* that if no ControlNet input image is uploaded, by default ControlNet will
* fallback onto img2img input image.
*/
(function () {
function getActiveImg2ImgTabImgSrc(img2imgTabs) {
const tabs = img2imgTabs.querySelectorAll('.tabitem');
const activeTabs = [...tabs].filter(tab => tab.style.display !== 'none');
if (!activeTabs) return;
const image = activeTabs[0].querySelector('.image-container img')
return image ? image.src : undefined;
}
function updateControlNetInputFallbackPreview(cnetInputContainers, imgDataURL) {
for (const container of cnetInputContainers) {
const badge = container.querySelector('.cnet-badge');
if (badge) badge.remove();
if (imgDataURL) {
// Do not add fallback image if controlnet input already exists.
if (container.querySelector('img'))
continue;
// Set the background image
container.style.backgroundImage = `url('${imgDataURL}')`;
// Set other background properties
container.style.backgroundPosition = 'center';
container.style.backgroundRepeat = 'no-repeat';
container.style.backgroundSize = 'contain';
container.title = "Img2Img input will be used if no ControlNet input is specified.";
const div = document.createElement('div');
div.classList.add('cnet-badge', 'primary', 'cnet-a1111-badge');
div.innerHTML = 'A1111';
container.appendChild(div);
} else {
container.style.backgroundImage = 'none';
}
}
}
const ImgChangeType = {
NO_CHANGE: 0,
REMOVE: 1,
ADD: 2,
SRC_CHANGE: 3,
};
function imgChangeObserved(mutationsList) {
// Iterate over all mutations that just occured
for (let mutation of mutationsList) {
// Check if the mutation is an addition or removal of a node
if (mutation.type === 'childList') {
// Check if nodes were added
if (mutation.addedNodes.length > 0) {
for (const node of mutation.addedNodes) {
if (node.tagName === 'IMG') {
return ImgChangeType.ADD;
}
}
}
// Check if nodes were removed
if (mutation.removedNodes.length > 0) {
for (const node of mutation.removedNodes) {
if (node.tagName === 'IMG') {
return ImgChangeType.REMOVE;
}
}
}
}
// Check if the mutation is a change of an attribute
else if (mutation.type === 'attributes') {
if (mutation.target.tagName === 'IMG' && mutation.attributeName === 'src') {
return ImgChangeType.SRC_CHANGE;
}
}
}
return ImgChangeType.NO_CHANGE;
}
let callback_registered = false;
onUiUpdate(() => {
if (callback_registered) return;
const cnetInputContainers = gradioApp().querySelectorAll(
"#img2img_controlnet_tabs .cnet-input-image-group .cnet-image");
if (!cnetInputContainers) return;
const img2imgTabs = gradioApp().querySelector("#mode_img2img");
if (!img2imgTabs) return;
// Every time img2img input updates, update fallback preview.
const img2imgContainers = img2imgTabs.querySelectorAll('.tabitem .image-container');
for (const container of img2imgContainers) {
new MutationObserver((mutationsList) => {
if (imgChangeObserved(mutationsList) !== ImgChangeType.NO_CHANGE) {
updateControlNetInputFallbackPreview(
cnetInputContainers,
getActiveImg2ImgTabImgSrc(img2imgTabs)
);
return;
}
}).observe(container, {
childList: true,
attributes: true,
attributeFilter: ['src'],
subtree: true,
});
}
// Every time controlnet input updates, update fallback preview.
for (const container of cnetInputContainers) {
new MutationObserver((mutationsList) => {
const changeObserved = imgChangeObserved(mutationsList);
if (changeObserved === ImgChangeType.REMOVE) {
updateControlNetInputFallbackPreview(
[container],
getActiveImg2ImgTabImgSrc(img2imgTabs)
);
return;
}
if (changeObserved === ImgChangeType.ADD ||
changeObserved === ImgChangeType.SRC_CHANGE) {
updateControlNetInputFallbackPreview(
[container],
undefined
);
return;
}
}).observe(container, {
childList: true,
attributes: true,
attributeFilter: ['src'],
subtree: true,
});
}
// Every time the img2img tab is switched, update fallback preview.
new MutationObserver((mutationsList) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
updateControlNetInputFallbackPreview(
cnetInputContainers,
getActiveImg2ImgTabImgSrc(img2imgTabs)
);
return;
}
}
}).observe(img2imgTabs.querySelector('.tab-nav'), { childList: true });
callback_registered = true;
});
})();