|
|
|
var photopeaWindow = null; |
|
var photopeaIframe = null; |
|
|
|
|
|
function onPhotopeaLoaded(iframe) { |
|
console.log("Photopea iFrame loaded"); |
|
photopeaWindow = iframe.contentWindow; |
|
photopeaIframe = iframe; |
|
|
|
|
|
|
|
|
|
createSendToPhotopeaButton("image_buttons_txt2img", window.txt2img_gallery); |
|
createSendToPhotopeaButton("image_buttons_img2img", window.img2img_gallery); |
|
createSendToPhotopeaButton("image_buttons_extras", window.extras_gallery); |
|
|
|
|
|
gradioApp().getElementById("photopeaIframeSlider").addEventListener('input', (event) => { |
|
|
|
const newHeight = parseInt(event.target.value); |
|
|
|
|
|
photopeaIframe.style.height = newHeight + 'px'; |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function createSendToPhotopeaButton(queryId, gallery) { |
|
const existingButton = gradioApp().querySelector(`#${queryId} button`); |
|
const newButton = existingButton.cloneNode(true); |
|
newButton.style.display = "flex"; |
|
newButton.id = `${queryId}_open_in_photopea`; |
|
newButton.title = "Send to Photopea" |
|
newButton.textContent = "\u{1F99C}"; |
|
newButton.addEventListener("click", () => openImageInPhotopea(gallery)); |
|
existingButton.parentNode.appendChild(newButton); |
|
} |
|
|
|
|
|
function goToPhotopeaTab() { |
|
|
|
const allButtons = gradioApp().querySelector('#tabs').querySelectorAll('button'); |
|
|
|
|
|
|
|
photopeaTabButton = Array.from(allButtons).find(button => button.textContent === 'Photopea '); |
|
photopeaTabButton.click(); |
|
} |
|
|
|
|
|
|
|
|
|
function goToImg2ImgInpaintUpload(onFinished) { |
|
|
|
switch_to_img2img(); |
|
const img2imgdiv = gradioApp().getElementById("mode_img2img"); |
|
|
|
waitForWebUiUpdate(img2imgdiv).then(() => { |
|
const allButtons = img2imgdiv.querySelectorAll("div.tab-nav > button"); |
|
const inpaintButton = |
|
Array.from(allButtons).find(button => button.textContent === 'Inpaint upload '); |
|
inpaintButton.click(); |
|
onFinished(); |
|
}); |
|
} |
|
|
|
|
|
|
|
|
|
function activeLayerOnly() { |
|
return gradioApp() |
|
.getElementById("photopea-use-active-layer-only") |
|
.querySelector("input[type=checkbox]").checked; |
|
} |
|
|
|
|
|
function openImageInPhotopea(originGallery) { |
|
var imageSizeMatches = true; |
|
const outgoingImg = originGallery.querySelectorAll("img")[0]; |
|
goToPhotopeaTab(); |
|
|
|
|
|
|
|
postMessageToPhotopea(getPhotopeaScriptString(getActiveDocumentSize)).then((response) => { |
|
const activeDocSize = response[0].split(","); |
|
if (outgoingImg.naturalWidth > activeDocSize[0] || |
|
outgoingImg.naturalHeight > activeDocSize[1]) { |
|
imageSizeMatches = false; |
|
} |
|
|
|
blobTob64(outgoingImg.src, (imageData) => { |
|
|
|
postMessageToPhotopea(`app.open("${imageData}", null, ${imageSizeMatches});`, "*") |
|
.then(() => { |
|
if (imageSizeMatches) { |
|
postMessageToPhotopea(`app.activeDocument.activeLayer.rasterize();`, "*"); |
|
} else { |
|
postMessageToPhotopea( |
|
`alert("New document created as the image sent is bigger than the active document");`, |
|
"*"); |
|
} |
|
}); |
|
}); |
|
|
|
}); |
|
} |
|
|
|
|
|
|
|
function getAndSendImageToWebUITab(webUiTab, sendToControlnet, imageWidgetIndex) { |
|
|
|
|
|
|
|
const saveMessage = activeLayerOnly() |
|
? getPhotopeaScriptString(exportSelectedLayerOnly) |
|
: 'app.activeDocument.saveToOE("png");'; |
|
|
|
postMessageToPhotopea(saveMessage) |
|
.then((resultArray) => { |
|
|
|
|
|
|
|
|
|
const base64Png = base64ArrayBuffer(resultArray[0]); |
|
sendImageToWebUi( |
|
webUiTab, |
|
sendToControlnet, |
|
imageWidgetIndex, |
|
b64toBlob(base64Png, "image/png")); |
|
}); |
|
} |
|
|
|
|
|
|
|
function sendImageToWebUi(webUiTab, sendToControlNet, controlnetModelIndex, blob) { |
|
const file = new File([blob], "photopea_output.png") |
|
|
|
switch (webUiTab) { |
|
case "txt2img": |
|
switch_to_txt2img(); |
|
break; |
|
case "img2img": |
|
switch_to_img2img(); |
|
break; |
|
case "extras": |
|
switch_to_extras(); |
|
break; |
|
} |
|
|
|
if (sendToControlNet) { |
|
|
|
const tabId = webUiTab === "txt2img" |
|
? "#txt2img_script_container" |
|
: "#img2img_script_container"; |
|
const controlNetDiv = gradioApp().querySelector(tabId).querySelector("#controlnet"); |
|
|
|
setImageOnControlNetInput(controlNetDiv, controlnetModelIndex, file); |
|
} else { |
|
|
|
const imageInput = gradioApp().getElementById(`mode_${webUiTab}`).querySelector("input[type='file']"); |
|
setImageOnInput(imageInput, file); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
function sendImageWithMaskSelectionToWebUi() { |
|
|
|
postMessageToPhotopea(getPhotopeaScriptString(selectionExists)) |
|
.then((response) => { |
|
if (response[0] === false) { |
|
|
|
|
|
postMessageToPhotopea(`alert("No selection in active document!");`); |
|
} else { |
|
|
|
|
|
goToImg2ImgInpaintUpload(() => { |
|
|
|
|
|
const fullMessage = |
|
getPhotopeaScriptString(createMaskFromSelection) + |
|
getPhotopeaScriptString(exportSelectedLayerOnly) + |
|
`app.activeDocument.activeLayer.remove();`; |
|
|
|
postMessageToPhotopea(fullMessage).then((resultArray) => { |
|
|
|
const base64Png = base64ArrayBuffer(resultArray[0]); |
|
const maskInput = gradioApp().getElementById("img_inpaint_mask").querySelector("input"); |
|
const blob = b64toBlob(base64Png, "image/png"); |
|
const file = new File([blob], "photopea_output.png"); |
|
setImageOnInput(maskInput, file); |
|
|
|
|
|
const saveMessage = activeLayerOnly() |
|
? getPhotopeaScriptString(exportSelectedLayerOnly) |
|
: 'app.activeDocument.saveToOE("png");'; |
|
|
|
postMessageToPhotopea(saveMessage) |
|
.then((resultArray) => { |
|
const base64Png = base64ArrayBuffer(resultArray[0]); |
|
const baseImgInput = gradioApp().getElementById("img_inpaint_base").querySelector("input"); |
|
const blob = b64toBlob(base64Png, "image/png"); |
|
const file = new File([blob], "photopea_output.png"); |
|
setImageOnInput(baseImgInput, file); |
|
}); |
|
}); |
|
}); |
|
} |
|
}); |
|
} |
|
|
|
|
|
function setImageOnControlNetInput(controlNetDiv, controlNetModelIndex, file) { |
|
if (controlNetAccordionIsCollapsed(controlNetDiv)) { |
|
|
|
|
|
controlNetDiv.querySelector("span.icon").click(); |
|
} |
|
waitForWebUiUpdate(controlNetDiv).then(() => { |
|
|
|
|
|
|
|
const tabs = controlNetDiv.querySelectorAll("div.tab-nav > button"); |
|
if (tabs !== null && tabs.length > 1) { |
|
tabs[controlNetModelIndex].click(); |
|
} |
|
|
|
|
|
|
|
|
|
imageInput = controlNetDiv.querySelectorAll("input[type='file']")[controlNetModelIndex * 2]; |
|
setImageOnInput(imageInput, file); |
|
} |
|
); |
|
} |
|
|
|
|
|
|
|
function setImageOnInput(imageInput, file) { |
|
|
|
const dt = new DataTransfer(); |
|
dt.items.add(file); |
|
const list = dt.files; |
|
|
|
|
|
imageInput.files = list; |
|
|
|
|
|
const event = new Event('change', { |
|
'bubbles': true, |
|
"composed": true |
|
}); |
|
imageInput.dispatchEvent(event); |
|
} |
|
|
|
|
|
function getPhotopeaScriptString(func) { |
|
return func.toString() + `${func.name}();` |
|
} |
|
|
|
|
|
|
|
async function postMessageToPhotopea(message) { |
|
var request = new Promise(function (resolve, reject) { |
|
var responses = []; |
|
var photopeaMessageHandle = function (response) { |
|
responses.push(response.data); |
|
|
|
|
|
if (response.data == "done") { |
|
window.removeEventListener("message", photopeaMessageHandle); |
|
resolve(responses) |
|
} |
|
}; |
|
|
|
window.addEventListener("message", photopeaMessageHandle); |
|
}); |
|
|
|
photopeaWindow.postMessage(message, "*"); |
|
return await request; |
|
} |
|
|
|
|
|
|
|
async function waitForWebUiUpdate(divToWatch) { |
|
const promise = new Promise((resolve, reject) => { |
|
|
|
const mutationConfig = { attributes: true, childList: true, subtree: true }; |
|
|
|
|
|
const onMutationHappened = (mutationList, observer) => { |
|
observer.disconnect(); |
|
resolve(); |
|
} |
|
const observer = new MutationObserver(onMutationHappened); |
|
observer.observe(divToWatch, mutationConfig); |
|
}); |
|
|
|
return await promise; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
function controlNetAccordionIsCollapsed(controlNetDiv) { |
|
|
|
|
|
const directDescendents = controlNetDiv.children; |
|
|
|
const sampleIframe = controlNetDiv.querySelectorAll("iframe")[0]; |
|
|
|
for(var i = 0; i < directDescendents.length; i++) { |
|
if(directDescendents[i].contains(sampleIframe)) { |
|
return directDescendents[i].style['display'] === 'none'; |
|
} |
|
} |
|
|
|
|
|
return false; |
|
} |
|
|