diff --git a/index.html b/index.html
index 3c2639c..d9e01dd 100644
--- a/index.html
+++ b/index.html
@@ -428,7 +428,7 @@
-
+
@@ -465,7 +465,7 @@
src="js/ui/tool/generic.js?v=3e678e0"
type="text/javascript">
-
+
diff --git a/js/lib/util.js b/js/lib/util.js
index 0607dcd..2955e2d 100644
--- a/js/lib/util.js
+++ b/js/lib/util.js
@@ -483,7 +483,7 @@ const makeElement = (
* @param {number}} blur
* @returns {HTMLCanvasElement}
*/
-const subtractBackground = (canvas, bb, bgImg, blur = 0) => {
+const subtractBackground = (canvas, bb, bgImg, blur = 0, threshold = 10) => {
// set up temp canvases
const bgCanvas = document.createElement("canvas");
const fgCanvas = document.createElement("canvas");
@@ -503,19 +503,22 @@ const subtractBackground = (canvas, bb, bgImg, blur = 0) => {
// 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) {
+ // one of these days i'm gonna learn how to use map reduce or whatever and stop iterating in for loops :(
+ // a la https://adamwathan.me/refactoring-to-collections/
+
+ // background rgb
var bgr = bgImgData.data[i];
var bgg = bgImgData.data[i + 1];
var bgb = bgImgData.data[i + 2];
-
+ // foreground rgb
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;
+ // delta rgb
+ const dr = Math.abs(bgr - fgr) > threshold ? fgr : 0;
+ const dg = Math.abs(bgg - fgb) > threshold ? fgb : 0;
+ const db = Math.abs(bgb - fgd) > threshold ? fgd : 0;
const pxChanged = dr > 0 && dg > 0 && db > 0;
diff --git a/js/ui/tool/dream.js b/js/ui/tool/dream.js
index 3bf03d5..66d17c7 100644
--- a/js/ui/tool/dream.js
+++ b/js/ui/tool/dream.js
@@ -538,7 +538,13 @@ const _generate = async (endpoint, request, bb, options = {}) => {
endpoint == "img2img" &&
toolbar._current_tool.state.removeBackground
) {
- canvas = subtractBackground(canvas, bb, dreamData.bgImg, 0);
+ canvas = subtractBackground(
+ canvas,
+ bb,
+ dreamData.bgImg,
+ toolbar._current_tool.state.carve_blur,
+ toolbar._current_tool.state.carve_threshold
+ );
}
commands.runCommand("drawImage", "Image Dream", {
@@ -1760,7 +1766,16 @@ const dreamTool = () =>
state,
"removeBackground",
"Remove Identical/BG Pixels",
- "icon-slice"
+ "icon-slice",
+ () => {
+ if (state.removeBackground) {
+ state.ctxmenu.carveBlurLabel.classList.remove("invisible");
+ state.ctxmenu.carveThresholdLabel.classList.remove("invisible");
+ } else {
+ state.ctxmenu.carveBlurLabel.classList.add("invisible");
+ state.ctxmenu.carveThresholdLabel.classList.add("invisible");
+ }
+ }
).checkbox;
// Overmasking Slider
@@ -1788,6 +1803,32 @@ const dreamTool = () =>
textStep: 1,
}
).slider;
+ // bg carve blur
+ state.ctxmenu.carveBlurLabel = _toolbar_input.slider(
+ state,
+ "carve_blur",
+ "BG Remove Blur",
+ {
+ min: 0,
+ max: 30,
+ step: 2,
+ textStep: 1,
+ }
+ ).slider;
+ state.ctxmenu.carveBlurLabel.classList.add("invisible");
+ // bg carve threshold
+ state.ctxmenu.carveThresholdLabel = _toolbar_input.slider(
+ state,
+ "carve_threshold",
+ "BG Remove Threshold",
+ {
+ min: 0,
+ max: 255,
+ step: 5,
+ textStep: 1,
+ }
+ ).slider;
+ state.ctxmenu.carveThresholdLabel.classList.add("invisible");
}
menu.appendChild(state.ctxmenu.cursorSizeSlider);
@@ -1805,6 +1846,8 @@ const dreamTool = () =>
// menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak);
// menu.appendChild(state.ctxmenu.preserveMasksLabel);
// menu.appendChild(document.createElement("br"));
+ menu.appendChild(state.ctxmenu.carveBlurLabel);
+ menu.appendChild(state.ctxmenu.carveThresholdLabel);
menu.appendChild(state.ctxmenu.outpaintTypeSelect);
menu.appendChild(state.ctxmenu.overMaskPxLabel);
menu.appendChild(state.ctxmenu.eagerGenerateCountLabel);
@@ -2326,7 +2369,16 @@ const img2imgTool = () =>
state,
"removeBackground",
"Remove Identical/BG Pixels",
- "icon-slice"
+ "icon-slice",
+ () => {
+ if (state.removeBackground) {
+ state.ctxmenu.carveBlurLabel.classList.remove("invisible");
+ state.ctxmenu.carveThresholdLabel.classList.remove("invisible");
+ } else {
+ state.ctxmenu.carveBlurLabel.classList.add("invisible");
+ state.ctxmenu.carveThresholdLabel.classList.add("invisible");
+ }
+ }
).checkbox;
// Border Mask Size Slider
@@ -2387,6 +2439,34 @@ const img2imgTool = () =>
state.ctxmenu.instructPix2PixImgCfgLabel.classList.add(
"instruct-pix2pix-img-cfg"
);
+
+ // bg carve blur
+ state.ctxmenu.carveBlurLabel = _toolbar_input.slider(
+ state,
+ "carve_blur",
+ "BG Remove Blur",
+ {
+ min: 0,
+ max: 30,
+ step: 2,
+ textStep: 1,
+ }
+ ).slider;
+ state.ctxmenu.carveBlurLabel.classList.add("invisible");
+
+ // bg carve threshold
+ state.ctxmenu.carveThresholdLabel = _toolbar_input.slider(
+ state,
+ "carve_threshold",
+ "BG Remove Threshold",
+ {
+ min: 0,
+ max: 255,
+ step: 5,
+ textStep: 1,
+ }
+ ).slider;
+ state.ctxmenu.carveThresholdLabel.classList.add("invisible");
}
menu.appendChild(state.ctxmenu.cursorSizeSlider);
@@ -2400,6 +2480,8 @@ const img2imgTool = () =>
menu.appendChild(array);
menu.appendChild(state.ctxmenu.keepUnmaskedBlurSlider);
// menu.appendChild(state.ctxmenu.keepUnmaskedBlurSliderLinebreak);
+ menu.appendChild(state.ctxmenu.carveBlurLabel);
+ menu.appendChild(state.ctxmenu.carveThresholdLabel);
menu.appendChild(state.ctxmenu.inpaintTypeSelect);
menu.appendChild(state.ctxmenu.denoisingStrengthSlider);
menu.appendChild(state.ctxmenu.instructPix2PixImgCfgLabel);