Spaces:
Runtime error
Runtime error
File size: 7,061 Bytes
c19ca42 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
(function () {
async function checkEditorAvailable() {
const LOCAL_EDITOR_PATH = '/openpose_editor_index';
const REMOTE_EDITOR_PATH = 'https://huchenlei.github.io/sd-webui-openpose-editor/';
async function testEditorPath(path) {
const res = await fetch(path);
return res.status === 200 ? path : null;
}
// Use local editor if the user has the extension installed. Fallback
// onto remote editor if the local editor is not ready yet.
// See https://github.com/huchenlei/sd-webui-openpose-editor/issues/53
// for more details.
return await testEditorPath(LOCAL_EDITOR_PATH) || await testEditorPath(REMOTE_EDITOR_PATH);
}
const cnetOpenposeEditorRegisteredElements = new Set();
let editorURL = null;
function loadOpenposeEditor() {
// Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits
// will only visible on web page and not sent to python.
function updateInput(target) {
let e = new Event("input", { bubbles: true })
Object.defineProperty(e, "target", { value: target })
target.dispatchEvent(e);
}
function navigateIframe(iframe, editorURL) {
function getPathname(rawURL) {
try {
return new URL(rawURL).pathname;
} catch (e) {
return rawURL;
}
}
return new Promise((resolve) => {
const darkThemeParam = document.body.classList.contains('dark') ?
new URLSearchParams({ theme: 'dark' }).toString() :
'';
window.addEventListener('message', (event) => {
const message = event.data;
if (message['ready']) resolve();
}, { once: true });
if ((editorURL.startsWith("http") ? iframe.src : getPathname(iframe.src)) !== editorURL) {
iframe.src = `${editorURL}?${darkThemeParam}`;
// By default assume 5 second is enough for the openpose editor
// to load.
setTimeout(resolve, 5000);
} else {
// If no navigation is required, immediately return.
resolve();
}
});
}
const tabs = gradioApp().querySelectorAll('.cnet-unit-tab');
tabs.forEach(tab => {
if (cnetOpenposeEditorRegisteredElements.has(tab)) return;
cnetOpenposeEditorRegisteredElements.add(tab);
const generatedImageGroup = tab.querySelector('.cnet-generated-image-group');
const editButton = generatedImageGroup.querySelector('.cnet-edit-pose');
editButton.addEventListener('click', async () => {
const inputImageGroup = tab.querySelector('.cnet-input-image-group');
const inputImage = inputImageGroup.querySelector('.cnet-image img');
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const modalId = editButton.id.replace('cnet-modal-open-', '');
const modalIframe = generatedImageGroup.querySelector('.cnet-modal iframe');
if (!editorURL) {
editorURL = await checkEditorAvailable();
if (!editorURL) {
alert("No openpose editor available.")
}
}
await navigateIframe(modalIframe, editorURL);
modalIframe.contentWindow.postMessage({
modalId,
imageURL: inputImage ? inputImage.src : undefined,
poseURL: downloadLink.href,
}, '*');
// Focus the iframe so that the focus is no longer on the `Edit` button.
// Pressing space when the focus is on `Edit` button will trigger
// the click again to resend the frame message.
modalIframe.contentWindow.focus();
});
/*
* Writes the pose data URL to an link element on input image group.
* Click a hidden button to trigger a backend rendering of the pose JSON.
*
* The backend should:
* - Set the rendered pose image as preprocessor generated image.
*/
function updatePreviewPose(poseURL) {
const downloadLink = generatedImageGroup.querySelector('.cnet-download-pose a');
const renderButton = generatedImageGroup.querySelector('.cnet-render-pose');
const poseTextbox = generatedImageGroup.querySelector('.cnet-pose-json textarea');
const allowPreviewCheckbox = tab.querySelector('.cnet-allow-preview input');
if (!allowPreviewCheckbox.checked)
allowPreviewCheckbox.click();
// Only set href when download link exists and needs an update. `downloadLink`
// can be null when user closes preview and click `Upload JSON` button again.
// https://github.com/Mikubill/sd-webui-controlnet/issues/2308
if (downloadLink !== null)
downloadLink.href = poseURL;
poseTextbox.value = poseURL;
updateInput(poseTextbox);
renderButton.click();
}
// Updates preview image when edit is done.
window.addEventListener('message', (event) => {
const message = event.data;
const modalId = editButton.id.replace('cnet-modal-open-', '');
if (message.modalId !== modalId) return;
updatePreviewPose(message.poseURL);
const closeModalButton = generatedImageGroup.querySelector('.cnet-modal .cnet-modal-close');
closeModalButton.click();
});
const inputImageGroup = tab.querySelector('.cnet-input-image-group');
const uploadButton = inputImageGroup.querySelector('.cnet-upload-pose input');
// Updates preview image when JSON file is uploaded.
uploadButton.addEventListener('change', (event) => {
const file = event.target.files[0];
if (!file)
return;
const reader = new FileReader();
reader.onload = function (e) {
const contents = e.target.result;
const poseURL = `data:application/json;base64,${btoa(contents)}`;
updatePreviewPose(poseURL);
};
reader.readAsText(file);
// Reset the file input value so that uploading the same file still triggers callback.
event.target.value = '';
});
});
}
onUiUpdate(loadOpenposeEditor);
})(); |