Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

magic wand feature #920

Open
tejas36026 opened this issue May 25, 2024 · 0 comments
Open

magic wand feature #920

tejas36026 opened this issue May 25, 2024 · 0 comments
Labels
Enhancement Enhance performance or improve usability of original features. Need Discussion Need discussion or investigation

Comments

@tejas36026
Copy link

tejas36026 commented May 25, 2024

`

<title>0. Design</title>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/magic-wand.js"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/magic-wand.js"></script>
<!-- <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script> -->
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>


<style>
  
  @import url(http://fonts.googleapis.com/css?family=Noto+Sans);
  html,
  body {
    height: 100%;
    margin: 0;
  }

.wrapper {
width: 400px !important;
height: 350px !important;
overflow: auto !important;
}
.content {
position: relative !important;
}
.canvas {
position: absolute;
}
.canvas:hover {
cursor: default;
}
.picture {
position: absolute;
}
.button {
padding: 4px;
margin: 4px;
border: 1px solid black;
float: left;
}
.button:hover {
background-color: blue;
color: white;
cursor: pointer;
}
#threshold {
width: 95px;
float: left;
}
#file-upload {
display: none;
}
.add-mode {
cursor: copy !important;
}
#imgcanvas {
position: relative;
}

#imgcanvas .wrapper {
position: absolute;
top: 121px;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
/* width: 400px; /
/
height: 350px; */
overflow: auto;
}

#imgcanvas .content {
position: relative;
}

</style>
Upload image and click on it
Create polygons by current selection
Paint the selection
Merge and Download
<input id="file-upload" type="file" accept="image/*" onchange="imgChange(this)" />
Blur radius:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.4.0/fabric.js" ></script> <script type="text/javascript" src="https://uicdn.toast.com/tui.code-snippet/v1.5.0/tui-code-snippet.min.js" ></script> <script type="text/javascript" src="https://uicdn.toast.com/tui-color-picker/v2.2.6/tui-color-picker.js" ></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js" ></script> <script src="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.js"></script> <script>
var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
  includeUI: {
    loadImage: {
        path: 'image.png',
        name: 'SampleImage',
      },
      // theme: blackTheme,
      initMenu: 'filter',
      menuBarPosition: 'bottom',
    },
    cssMaxWidth: 700,
    cssMaxHeight: 500,
    usageStatistics: false,
  });
  window.onresize = function () {
    imageEditor.ui.resizeEditor();
  };  

window.onload = function() {
colorThreshold = 15;
blurRadius = 5;
simplifyTolerant = 0;
simplifyCount = 30;
hatchLength = 4;
hatchOffset = 0;

imageInfo = null;
cacheInd = null;
mask = null;
oldMask = null;
downPoint = null;
allowDraw = false;
addMode = false;
currentThreshold = colorThreshold;

document.onkeydown = onKeyDown;
document.onkeyup = onKeyUp;

showThreshold();
document.getElementById("blurRadius").value = blurRadius;
setInterval(function () { hatchTick(); }, 300);
imgChange();

}

function uploadClick() {
document.getElementById("file-upload").click();
}

function onRadiusChange(e) {
blurRadius = e.target.value;
}

function imgChange() {
var img = document.getElementById("test-picture");
img.setAttribute('src', 'image.png');
img.onload = function() {
window.initCanvas(img);
};
}

function initCanvas(img) {
var cvs = document.getElementById("resultCanvas");
console.log(cvs);
var cvs1 = imageEditor._graphics.getCanvas();
cvs1.onmouseup = function() {
onMouseUp.apply(this, arguments);
};
cvs1.onmousedown = function() {
onMouseDown.apply(this, arguments);
};
cvs1.onmousemove = function() {
onMouseMove.apply(this, arguments);
};
console.log(cvs1);
console.log(cvs1.canvasElement);

cvs.width = img.width;
cvs.height = img.height;

imageInfo = {
    width: img.width,
    height: img.height,
    context: cvs.getContext("2d")
};
mask = null;

var tempCtx = document.createElement("canvas").getContext("2d");
tempCtx.canvas.width = imageInfo.width;
tempCtx.canvas.height = imageInfo.height;
tempCtx.drawImage(img, 0, 0);
imageInfo.data = tempCtx.getImageData(0, 0, imageInfo.width, imageInfo.height);

}
function getMousePosition(e) {
var p = $(e.target).offset(),
x = Math.round((e.clientX || e.pageX) - p.left),
y = Math.round((e.clientY || e.pageY) - p.top);
return { x: x, y: y };
}

function onMouseDown(e) {
if (e.button == 0) {
allowDraw = true;
addMode = e.ctrlKey;
downPoint = getMousePosition(e);
drawMask(downPoint.x, downPoint.y);
} else {
allowDraw = false;
addMode = false;
oldMask = null;
}
}
function onMouseMove(e) {
if (allowDraw) {
var p = getMousePosition(e);
if (p.x != downPoint.x || p.y != downPoint.y) {
var dx = p.x - downPoint.x,
dy = p.y - downPoint.y,
len = Math.sqrt(dx * dx + dy * dy),
adx = Math.abs(dx),
ady = Math.abs(dy),
sign = adx > ady ? dx / adx : dy / ady;
sign = sign < 0 ? sign / 5 : sign / 3;
var thres = Math.min(Math.max(colorThreshold + Math.floor(sign * len), 1), 255);
//var thres = Math.min(colorThreshold + Math.floor(len / 3), 255);
if (thres != currentThreshold) {
currentThreshold = thres;
drawMask(downPoint.x, downPoint.y);
}
}
}
}

function onMouseUp(e) {
allowDraw = false;
addMode = false;
oldMask = null;
currentThreshold = colorThreshold;
}
function onKeyDown(e) {
if (e.keyCode == 17) document.getElementById("resultCanvas").classList.add("add-mode");
}
function onKeyUp(e) {
if (e.keyCode == 17) document.getElementById("resultCanvas").classList.remove("add-mode");
}
function showThreshold() {
document.getElementById("threshold").innerHTML = "Threshold: " + currentThreshold;
}
function drawMask(x, y) {
if (!imageInfo) return;

showThreshold();

var image = {
    data: imageInfo.data.data,
    width: imageInfo.width,
    height: imageInfo.height,
    bytes: 4
};

if (addMode && !oldMask) {
	oldMask = mask;
}

let old = oldMask ? oldMask.data : null;

mask = MagicWand.floodFill(image, x, y, currentThreshold, old, true);
if (mask) mask = MagicWand.gaussBlurOnlyBorder(mask, blurRadius, old);

if (addMode && oldMask) {
	mask = mask ? concatMasks(mask, oldMask) : oldMask;
}

drawBorder();

}

function hatchTick() {
hatchOffset = (hatchOffset + 1) % (hatchLength * 2);
drawBorder(true);
}

function drawBorder(noBorder) {
if (!mask) return;

var x,y,i,j,k,
    w = imageInfo.width,
    h = imageInfo.height,
    ctx = imageInfo.context,
    imgData = ctx.createImageData(w, h),
    res = imgData.data;

if (!noBorder) cacheInd = MagicWand.getBorderIndices(mask);

ctx.clearRect(0, 0, w, h);

var len = cacheInd.length;
for (j = 0; j < len; j++) {
    i = cacheInd[j];
    x = i % w; // calc x by index
    y = (i - x) / w; // calc y by index
    k = (y * w + x) * 4; 
    if ((x + y + hatchOffset) % (hatchLength * 2) < hatchLength) { // detect hatch color 
        res[k + 3] = 255; // black, change only alpha
    } else {
        res[k] = 255; // white
        res[k + 1] = 255;
        res[k + 2] = 255;
        res[k + 3] = 255;
    }
}

ctx.putImageData(imgData, 0, 0);

}
function trace() {
var cs = MagicWand.traceContours(mask);
cs = MagicWand.simplifyContours(cs, simplifyTolerant, simplifyCount);

mask = null;

var ctx = imageInfo.context;
ctx.clearRect(0, 0, imageInfo.width, imageInfo.height);
ctx.beginPath();
for (var i = 0; i < cs.length; i++) {
    if (!cs[i].inner) continue;
    var ps = cs[i].points;
    ctx.moveTo(ps[0].x, ps[0].y);
    for (var j = 1; j < ps.length; j++) {
        ctx.lineTo(ps[j].x, ps[j].y);
    }
}
ctx.strokeStyle = "red";
ctx.stroke();    
//outer
ctx.beginPath();
for (var i = 0; i < cs.length; i++) {
    if (cs[i].inner) continue;
    var ps = cs[i].points;
    ctx.moveTo(ps[0].x, ps[0].y);
    for (var j = 1; j < ps.length; j++) {
        ctx.lineTo(ps[j].x, ps[j].y);
    }
}
ctx.strokeStyle = "blue";
ctx.stroke();    

}
function paint(color, alpha) {
if (!mask) return;

var rgba = hexToRgb(color, alpha);

var x,y,
		data = mask.data,
		bounds = mask.bounds,
    maskW = mask.width,
    w = imageInfo.width,
    h = imageInfo.height,
    ctx = imageInfo.context,
    imgData = ctx.createImageData(w, h),
    res = imgData.data;

for (y = bounds.minY; y <= bounds.maxY; y++) {
  for (x = bounds.minX; x <= bounds.maxX; x++) {
  		if (data[y * maskW + x] == 0) continue;
      k = (y * w + x) * 4; 
      res[k] = rgba[0];
      res[k + 1] = rgba[1];
      res[k + 2] = rgba[2];
        res[k + 3] = rgba[3];
  }
	}

mask = null;

ctx.putImageData(imgData, 0, 0);

}
function hexToRgb(hex, alpha) {
var int = parseInt(hex, 16);
var r = (int >> 16) & 255;
var g = (int >> 8) & 255;
var b = int & 255;

return [r,g,b, Math.round(alpha * 255)];
}
function concatMasks(mask, old) {
let
data1 = old.data,
data2 = mask.data,
w1 = old.width,
w2 = mask.width,
b1 = old.bounds,
b2 = mask.bounds,
b = {
minX: Math.min(b1.minX, b2.minX),
minY: Math.min(b1.minY, b2.minY),
maxX: Math.max(b1.maxX, b2.maxX),
maxY: Math.max(b1.maxY, b2.maxY)
},
w = old.width,
h = old.height,
i, j, k, k1, k2, len;

let result = new Uint8Array(w * h);

  len = b1.maxX - b1.minX + 1;
  i = b1.minY * w + b1.minX;
  k1 = b1.minY * w1 + b1.minX;
  k2 = b1.maxY * w1 + b1.minX + 1;

for (k = k1; k < k2; k += w1) {
  result.set(data1.subarray(k, k + len), i); // copy row
  i += w;
}

len = b2.maxX - b2.minX + 1;
i = b2.minY * w + b2.minX;
k1 = b2.minY * w2 + b2.minX;
k2 = b2.maxY * w2 + b2.minX + 1;

for (k = k1; k < k2; k += w2) {
for (j = 0; j < len; j++) {
if (data2[k + j] === 1) result[i + j] = 1;
}
i += w;
}

return {
	data: result,
	width: w,
	height: h,
	bounds: b
};

}
</script>

`

this is my code that work on magic wand using magic-wand.js now i need this image to be viewed in the tui image editor where i can apply other filters as well? what changes shall i incorporate ? i tried using the

var cvs = imageEditor._graphics.getCanvas()
but it failed to load and for image
var img = imageEditor.toDataURL()
but that also did not work. what should i do ?

@tejas36026 tejas36026 added Enhancement Enhance performance or improve usability of original features. Need Discussion Need discussion or investigation labels May 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Enhance performance or improve usability of original features. Need Discussion Need discussion or investigation
Projects
None yet
Development

No branches or pull requests

1 participant