Download extensions/CHECK/sd-webui-llul/javascript/llul.js from dikdimon/aasdfdas: direct link, hf CLI and curl.
- Browser
- Download file 8.5 kB
-
https://huggingface.co/dikdimon/aasdfdas/resolve/main/extensions/CHECK/sd-webui-llul/javascript/llul.js
- Command line
-
hf download hf://dikdimon/aasdfdas/extensions/CHECK/sd-webui-llul/javascript/llul.js
-
curl -L -o llul.js https://huggingface.co/dikdimon/aasdfdas/resolve/main/extensions/CHECK/sd-webui-llul/javascript/llul.js
8.5 kB
| (function () { | |
| if (!globalThis.LLuL) globalThis.LLuL = {}; | |
| const LLuL = globalThis.LLuL; | |
| function id(type, s) { | |
| return `llul-${type}-${s}`; | |
| } | |
| function isDark() { | |
| return gradioApp().querySelector('.dark') !== null; | |
| } | |
| const M = 2; | |
| function setSize(canvas, width, height) { | |
| width = Math.floor(+width / M); | |
| height = Math.floor(+height / M); | |
| if (canvas.width != width) canvas.width = width; | |
| if (canvas.height != height) canvas.height = height; | |
| } | |
| function updateXY(canvas) { | |
| let x = +canvas.dataset.x, | |
| y = +canvas.dataset.y, | |
| m = +canvas.dataset.m, | |
| mm = Math.pow(2, m), | |
| w = +canvas.width * M, | |
| h = +canvas.height * M; | |
| if (x < 0) x = 0; | |
| if (w < x + w / mm) x = Math.floor(w - w / mm); | |
| if (y < 0) y = 0; | |
| if (h < y + h / mm) y = Math.floor(h - h / mm); | |
| canvas.dataset.x = x; | |
| canvas.dataset.y = y; | |
| canvas.dataset.m = m; | |
| canvas.parentNode.querySelector('.llul-pos-x').value = x; | |
| canvas.parentNode.querySelector('.llul-pos-y').value = y; | |
| } | |
| let last_image = new Image(); | |
| let hide_image = true; | |
| async function draw(canvas) { | |
| const | |
| x = +canvas.dataset.x, | |
| y = +canvas.dataset.y, | |
| m = +canvas.dataset.m, | |
| mm = Math.pow(2, m), | |
| w = +canvas.width, | |
| h = +canvas.height, | |
| bg = canvas.dataset.bg; | |
| const ctx = canvas.getContext('2d'); | |
| if (bg) { | |
| if (last_image?.src === bg) { | |
| // do nothing | |
| } else { | |
| await (new Promise(resolve => { | |
| last_image.onload = () => resolve(); | |
| last_image.src = bg; | |
| })); | |
| } | |
| hide_image = false; | |
| } else { | |
| last_image.src = ''; | |
| hide_image = true; | |
| } | |
| if (last_image.src && !hide_image) { | |
| ctx.drawImage(last_image, 0, 0, +last_image.width, +last_image.height, 0, 0, +canvas.width, +canvas.height); | |
| } else { | |
| const bgcolor = isDark() ? 'black' : 'white'; | |
| ctx.fillStyle = bgcolor; | |
| ctx.fillRect(0, 0, +canvas.width, +canvas.height); | |
| } | |
| ctx.fillStyle = 'gray'; | |
| ctx.fillRect(x / M, y / M, Math.floor(w / mm), Math.floor(h / mm)); | |
| } | |
| async function update_gradio(type, canvas) { | |
| await LLuL.js2py(type, 'x', +canvas.dataset.x); | |
| await LLuL.js2py(type, 'y', +canvas.dataset.y); | |
| } | |
| function init(type) { | |
| const $$ = (x,n) => Array.from(gradioApp().querySelectorAll(x)).at(n); | |
| const $ = x => $$(x, -1); | |
| if (!$('#' + id(type, 'accordion'))) return false; | |
| const cont = $('#' + id(type, 'container')); | |
| const x = $('#' + id(type, 'x')); | |
| const y = $('#' + id(type, 'y')); | |
| const m = $(`#${id(type, 'm')} input[type=number]`); | |
| const ms = $(`#${id(type, 'm')} input[type=range]`); | |
| if (!cont || !x || !y || !m || !ms) return false; | |
| if (cont.querySelector('canvas')) return true; // already called | |
| const width = $$(`#${type}_width input[type=number]`, 0); | |
| const height = $$(`#${type}_height input[type=number]`, 0); | |
| const width2 = $$(`#${type}_width input[type=range]`, 0); | |
| const height2 = $$(`#${type}_height input[type=range]`, 0); | |
| const pos_x = Math.floor(+width.value / 4); | |
| const pos_y = Math.floor(+height.value / 4); | |
| const pos_cont = document.createElement('div'); | |
| pos_cont.innerHTML = ` | |
| <div class="llul-pos" id="llul-${type}-pos"> | |
| <label>x:<input type="number" value="${pos_x}" min="0" step="1" class="llul-pos-x" id="llul-${type}-pos-x"></label> | |
| <label>y:<input type="number" value="${pos_y}" min="0" step="1" class="llul-pos-y" id="llul-${type}-pos-y"></label> | |
| </div> | |
| `; | |
| const canvas = document.createElement('canvas'); | |
| canvas.style.border = '1px solid gray'; | |
| canvas.dataset.x = pos_x; | |
| canvas.dataset.y = pos_y; | |
| canvas.dataset.m = m.value; | |
| const bg_cont = document.createElement('div'); | |
| bg_cont.classList.add('llul-bg-setting'); | |
| bg_cont.innerHTML = ` | |
| <span>Load BG</span> | |
| <span>Erase BG</span> | |
| <input type="file" style="display:none"> | |
| `; | |
| for (let ele of [width, height, width2, height2, m, ms]) { | |
| ele.addEventListener('input', e => { | |
| canvas.dataset.m = +m.value; | |
| setSize(canvas, width.value, height.value); | |
| updateXY(canvas); | |
| draw(canvas); | |
| }); | |
| } | |
| // | |
| // Event Listeners | |
| // | |
| // canvas | |
| let dragging = false; | |
| let last_x, last_y; | |
| canvas.addEventListener('pointerdown', e => { | |
| e.preventDefault(); | |
| dragging = true; | |
| last_x = e.offsetX; | |
| last_y = e.offsetY; | |
| }); | |
| canvas.addEventListener('pointerup', async e => { | |
| e.preventDefault(); | |
| dragging = false; | |
| await update_gradio(type, canvas); | |
| }); | |
| canvas.addEventListener('pointermove', e => { | |
| if (!dragging) return; | |
| const dx = e.offsetX - last_x, dy = e.offsetY - last_y; | |
| const x = +canvas.dataset.x, y = +canvas.dataset.y; | |
| canvas.dataset.x = x + dx * M; | |
| canvas.dataset.y = y + dy * M; | |
| last_x = e.offsetX; | |
| last_y = e.offsetY; | |
| updateXY(canvas); | |
| draw(canvas); | |
| }); | |
| // bg_cont | |
| function set_bg(url) { | |
| canvas.dataset.bg = url; | |
| draw(canvas); | |
| } | |
| bg_cont.querySelector('input[type=file]').addEventListener('change', e => { | |
| const ele = e.target; | |
| const files = ele.files; | |
| if (files.length != 0) { | |
| const file = files[0]; | |
| const r = new FileReader(); | |
| r.onload = () => set_bg(r.result); | |
| r.readAsDataURL(file); | |
| } | |
| ele.value = ''; | |
| }, false); | |
| bg_cont.addEventListener('click', e => { | |
| const ele = e.target; | |
| if (ele.textContent == 'Load BG') { | |
| bg_cont.querySelector('input[type=file]').click(); | |
| } else if (ele.textContent == 'Erase BG') { | |
| set_bg(''); | |
| } | |
| }); | |
| // pos_cont | |
| //pos_cont.addEventListener('input', e => { | |
| // const ele = e.target; | |
| // let x = +canvas.dataset.x; | |
| // let y = +canvas.dataset.y; | |
| // if (ele.classList.contains(`llul-pos-x`)) { | |
| // x = +ele.value; | |
| // } else if (ele.classList.contains(`llul-pos-y`)) { | |
| // y = +ele.value; | |
| // } else { | |
| // return; | |
| // } | |
| // canvas.dataset.x = x; | |
| // canvas.dataset.y = y; | |
| // updateXY(canvas); | |
| // draw(canvas); | |
| // update_gradio(type, canvas); | |
| //}); | |
| cont.appendChild(pos_cont); | |
| cont.appendChild(canvas); | |
| cont.appendChild(bg_cont); | |
| setSize(canvas, width.value, height.value); | |
| updateXY(canvas); | |
| draw(canvas); | |
| return true; | |
| } | |
| function init2(type, init_fn) { | |
| const repeat_until = (fn, resolve) => { | |
| const v = fn(); | |
| if (v) { | |
| resolve(v); | |
| } else { | |
| setTimeout(() => repeat_until(fn, resolve), 500); | |
| } | |
| }; | |
| return new Promise(resolve => repeat_until(() => init_fn(type), resolve)); | |
| } | |
| function init_LLuL() { | |
| if (!LLuL.txt2img) { | |
| LLuL.txt2img = init2('txt2img', init); | |
| if (LLuL.txt2img) { | |
| LLuL.txt2img.then(() => console.log('[LLuL] txt2img initialized')); | |
| } | |
| } | |
| if (!LLuL.img2img) { | |
| LLuL.img2img = init2('img2img', init); | |
| if (LLuL.img2img) { | |
| LLuL.img2img.then(() => console.log('[LLuL] img2img initialized')); | |
| } | |
| } | |
| return LLuL.txt2img && LLuL.img2img; | |
| } | |
| function apply() { | |
| const ok = init_LLuL(); | |
| if (!ok) { | |
| setTimeout(apply, 500); | |
| } | |
| } | |
| apply(); | |
| })(); | |