kinda janky identical pixel removal?

surprise

"manual scripts" has kinda become inadequate for all this branch is doing now lol
This commit is contained in:
tim h 2023-01-29 16:39:00 -06:00
parent 0400b9b284
commit 02bf04c257
9 changed files with 133 additions and 8 deletions

View file

@ -105,6 +105,12 @@
mask-image: url("../res/icons/paintbrush.svg");
}
.ui.inline-icon.icon-slice::after,
.ui.icon > .icon-slice {
-webkit-mask-image: url("../res/icons/slice.svg");
mask-image: url("../res/icons/slice.svg");
}
.ui.inline-icon.icon-save::after,
.ui.icon > .icon-save {
-webkit-mask-image: url("../res/icons/save.svg");

View file

@ -5,7 +5,7 @@
<title>openOutpaint 🐠</title>
<!-- CSS Variables -->
<link href="css/colors.css?v=f732f19" rel="stylesheet" />
<link href="css/icons.css?v=466e14e" rel="stylesheet" />
<link href="css/icons.css?v=599e732" rel="stylesheet" />
<link href="css/index.css?v=61e08f5" rel="stylesheet" />
<link href="css/layers.css?v=92c0352" rel="stylesheet" />
@ -434,7 +434,7 @@
<script src="js/defaults.js?v=5b06818" type="text/javascript"></script>
<!-- Base Libs -->
<script src="js/lib/util.js?v=e82dd04" type="text/javascript"></script>
<script src="js/lib/util.js?v=f5ef803" type="text/javascript"></script>
<script src="js/lib/events.js?v=2ab7933" type="text/javascript"></script>
<script src="js/lib/db.js?v=434363b" type="text/javascript"></script>
<script src="js/lib/input.js?v=769485c" type="text/javascript"></script>
@ -468,7 +468,7 @@
src="js/ui/tool/generic.js?v=3e678e0"
type="text/javascript"></script>
<script src="js/ui/tool/dream.js?v=5050800" type="text/javascript"></script>
<script src="js/ui/tool/dream.js?v=3f03af8" type="text/javascript"></script>
<script
src="js/ui/tool/maskbrush.js?v=d88810f"
type="text/javascript"></script>

View file

@ -474,3 +474,55 @@ const makeElement = (
return el;
};
/**
* Subtracts identical (or damn close) pixels from new dreams
* @param {HTMLCanvasElement} canvas
* @param {BoundingBox} bb
* @param {HTMLImageElement} bgImg
* @param {number}} blur
* @returns {HTMLCanvasElement}
*/
const subtractBackground = (canvas, bb, bgImg, blur = 0) => {
// set up temp canvases
const bgCanvas = document.createElement("canvas");
const fgCanvas = document.createElement("canvas");
const returnCanvas = document.createElement("canvas");
bgCanvas.width = fgCanvas.width = returnCanvas.width = bb.w;
bgCanvas.height = fgCanvas.height = returnCanvas.height = bb.h;
const bgCtx = bgCanvas.getContext("2d");
const fgCtx = fgCanvas.getContext("2d");
const returnCtx = returnCanvas.getContext("2d");
returnCtx.rect(0, 0, bb.w, bb.h);
returnCtx.fill();
// draw previous "background" image
bgCtx.drawImage(bgImg, 0, 0, bb.w, bb.h);
bgCtx.filter = "blur(" + blur + "px)";
// ... turn that into base64
const bgImgData = bgCtx.getImageData(0, 0, bb.w, bb.h);
// draw new image
fgCtx.drawImage(canvas, 0, 0);
const fgImgData = fgCtx.getImageData(0, 0, bb.w, bb.h);
// const blendImgData = blendCtx.getImageData(0, 0, bb.w, bb.h);
for (var i = 0; i < bgImgData.data.length; i += 4) {
var bgr = bgImgData.data[i];
var bgg = bgImgData.data[i + 1];
var bgb = bgImgData.data[i + 2];
var fgr = fgImgData.data[i];
var fgb = fgImgData.data[i + 1];
var fgd = fgImgData.data[i + 2];
const dr = Math.abs(bgr - fgr) > 10 ? fgr : 0;
const dg = Math.abs(bgg - fgb) > 10 ? fgb : 0;
const db = Math.abs(bgb - fgd) > 10 ? fgd : 0;
const pxChanged = dr > 0 && dg > 0 && db > 0;
fgImgData.data[i + 3] = pxChanged ? 255 : 0;
}
returnCtx.putImageData(fgImgData, 0, 0);
return returnCanvas;
};

View file

@ -92,9 +92,19 @@ const generating = (val) => {
*
* @param {"txt2img" | "img2img"} endpoint Endpoint to send the request to
* @param {StableDiffusionRequest} request Stable diffusion request
* @param {BoundingBox} bb Optional: Generated image placement location
* @returns {Promise<string[]>}
*/
const _dream = async (endpoint, request) => {
const _dream = async (endpoint, request, bb = null) => {
var bgImg = null;
if (
endpoint == "img2img" &&
bb &&
toolbar._current_tool.state.removeBackground
) {
bgImg = uil.getVisible(bb, {includeBg: false});
}
const apiURL = `${host}${config.api.path}${endpoint}`;
// if script fields are populated add them to the request
var scriptName = document.getElementById("script-name-input").value;
@ -169,6 +179,7 @@ const _dream = async (endpoint, request) => {
var returnData = {
images: data.images,
seeds: responseSubdata.all_seeds,
bgImg: bgImg,
};
return returnData;
};
@ -442,7 +453,7 @@ const _generate = async (endpoint, request, bb, options = {}) => {
});
imageCollection.inputElement.appendChild(interruptButton);
var dreamData = await _dream(endpoint, requestCopy);
var dreamData = await _dream(endpoint, requestCopy, bb);
images.push(...dreamData.images);
seeds.push(...dreamData.seeds);
stopDrawingStatus = true;
@ -505,7 +516,7 @@ const _generate = async (endpoint, request, bb, options = {}) => {
// load the image data after defining the closure
img.src = "data:image/png;base64," + images[at];
img.addEventListener("load", () => {
const canvas = document.createElement("canvas");
let canvas = document.createElement("canvas");
canvas.width = bb.w;
canvas.height = bb.h;
const ctx = canvas.getContext("2d");
@ -519,6 +530,15 @@ const _generate = async (endpoint, request, bb, options = {}) => {
commands.runCommand("addLayer", "Added Layer", {});
}
if (
endpoint == "img2img" &&
toolbar._current_tool.state.removeBackground
) {
//TODO SERIOUSLY CHECK FOR MORE THINGS HERE
canvas = subtractBackground(canvas, bb, dreamData.bgImg, 0);
// do something else too probably idunno
}
commands.runCommand("drawImage", "Image Dream", {
x: bb.x,
y: bb.y,
@ -545,7 +565,7 @@ const _generate = async (endpoint, request, bb, options = {}) => {
addline(` + Model = ${modelAutoComplete.value}`);
addline(` + +Prompt = ${request.prompt}`);
addline(` + -Prompt = ${request.negative_prompt}`);
addline(` + Styles = ${request.styles.join(", ")}`, false);
addline(` + Styles = ${request.styles.join(", ")}`, false);
commands.runCommand(
"drawImage",
@ -1727,6 +1747,14 @@ const dreamTool = () =>
"icon-paintbrush"
).checkbox;
// Remove Identical/Background Pixels Checkbox
state.ctxmenu.removeBackgroundLabel = _toolbar_input.checkbox(
state,
"removeBackground",
"Remove Identical/BG Pixels",
"icon-slice"
).checkbox;
// Overmasking Slider
state.ctxmenu.overMaskPxLabel = _toolbar_input.slider(
state,
@ -1762,6 +1790,7 @@ const dreamTool = () =>
array.appendChild(state.ctxmenu.invertMaskLabel);
array.appendChild(state.ctxmenu.preserveMasksLabel);
//menu.appendChild(document.createElement("br"));
array.appendChild(state.ctxmenu.removeBackgroundLabel);
array.appendChild(state.ctxmenu.keepUnmaskedLabel);
menu.appendChild(array);
menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider);
@ -2284,6 +2313,14 @@ const img2imgTool = () =>
"icon-box-select"
).checkbox;
// Remove Identical/Background Pixels Checkbox
state.ctxmenu.removeBackgroundLabel = _toolbar_input.checkbox(
state,
"removeBackground",
"Remove Identical/BG Pixels",
"icon-slice"
).checkbox;
// Border Mask Size Slider
state.ctxmenu.borderMaskSlider = _toolbar_input.slider(
state,
@ -2334,6 +2371,7 @@ const img2imgTool = () =>
array.appendChild(state.ctxmenu.snapToGridLabel);
array.appendChild(state.ctxmenu.invertMaskLabel);
array.appendChild(state.ctxmenu.preserveMasksLabel);
array.appendChild(state.ctxmenu.removeBackgroundLabel);
array.appendChild(state.ctxmenu.keepUnmaskedLabel);
menu.appendChild(array);
menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider);

View file

@ -5,7 +5,7 @@
<title>openOutpaint 🐠</title>
<!-- CSS Variables -->
<link href="../css/colors.css?v=f732f19" rel="stylesheet" />
<link href="../css/icons.css?v=466e14e" rel="stylesheet" />
<link href="../css/icons.css?v=599e732" rel="stylesheet" />
<link href="../css/index.css?v=61e08f5" rel="stylesheet" />
<link href="../css/layers.css?v=92c0352" rel="stylesheet" />

9
res/icons/fish.svg Normal file
View file

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M6.5 12c.94-3.46 4.94-6 8.5-6 3.56 0 6.06 2.54 7 6-.94 3.47-3.44 6-7 6s-7.56-2.53-8.5-6Z"></path>
<path d="M18 12v.5"></path>
<path d="M16 17.93a9.77 9.77 0 0 1 0-11.86"></path>
<path d="M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33"></path>
<path d="M10.46 7.26C10.2 5.88 9.17 4.24 8 3h5.8a2 2 0 0 1 1.98 1.67l.23 1.4"></path>
<path d="m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98"></path>
</svg>

After

Width:  |  Height:  |  Size: 678 B

View file

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 9v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h7"></path>
<line x1="16" y1="5" x2="22" y2="5"></line>
<circle cx="9" cy="9" r="2"></circle>
<path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"></path>
</svg>

After

Width:  |  Height:  |  Size: 414 B

8
res/icons/scissors.svg Normal file
View file

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="6" cy="6" r="3"></circle>
<circle cx="6" cy="18" r="3"></circle>
<line x1="20" y1="4" x2="8.12" y2="15.88"></line>
<line x1="14.47" y1="14.48" x2="20" y2="20"></line>
<line x1="8.12" y1="8.12" x2="12" y2="12"></line>
</svg>

After

Width:  |  Height:  |  Size: 428 B

5
res/icons/slice.svg Normal file
View file

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m8 14-6 6h9v-3"></path>
<path d="M18.37 3.63 8 14l3 3L21.37 6.63a2.12 2.12 0 1 0-3-3Z"></path>
</svg>

After

Width:  |  Height:  |  Size: 297 B