Draw A Box Around Canvas Getimagedata
Solution 1:
Logic steps
To scan for the bounding box of a shape you could do the following steps. Assuming you have extracted the bitmap (ImageData
) from canvas, x
and y
are used to iterate over the bitmap:
Scan from top to bottom, line by line. At first solid pixel found, store current
y
position asy1
, skip to next stepScan from bottom to
y1
, line by line. At first solid pixel found, store currenty
position asy2
Scan horizontally from left to right within
y1
toy2
. Initializex1
with width of canvas. When a solid pixel is found on current line andx
has lower value than currentx1
, setx1
= currentx
and skip to next lineScan horizontally from right to
x1
. Initializex2
with 0. When a solid pixel is found on current line andx
has higher value than currentx2
, setx2
= currentx
and skip to next lineSize of area would of course be:
width = x2 - x1
,height = y2 - y1
.
Anti-aliased shaped can affect the size. You can include checking alpha channel for solid to reduce this influence.
The scanning can be optimized for left and right edges by updating the loop to use the new x1/x2 value as limits. Use Uint32Array
to check for pixel values.
Proof-of-concept
A non-optimized implementation showing the result of the above steps. It will check any non-alpha values. You can for example replace 0xff000000 with 0x80000000 to check alpha values > 127 if you want to reduce influence of the anti-aliasing. If you don't have alpha just check for the actual color value (note that some images are color corrected so a tolerance can be wise to consider).
var ctx = document.querySelector("canvas").getContext("2d"),
btn = document.querySelector("button"),
w = ctx.canvas.width,
h = ctx.canvas.height,
img = newImage();
img.crossOrigin = ""; img.onload = plot; img.src = "//i.imgur.com/lfsyAEc.png";
btn.onclick = plot;
functionplot() {
var iw = img.width, ih = img.height,
x = Math.random() * (w - iw * 0.5), y = Math.random() * (h - ih * 0.5),
s = (Math.random() * 30 - 15)|0;
ctx.clearRect(0, 0, w, h);
ctx.translate(x, y);
ctx.rotate(Math.random() * Math.PI - Math.PI * 0.5);
ctx.drawImage(img, -(iw + s) * 0.5, -(ih + s) * 0.5, iw + s, ih + s);
ctx.setTransform(1,0,0,1,0,0);
analyze();
}
functionanalyze() {
var data = newUint32Array(ctx.getImageData(0, 0, w, h).data.buffer),
len = data.length,
x, y, y1, y2, x1 = w, x2 = 0;
// y1for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) {
if (data[y * w + x] & 0xff000000) {
y1 = y;
y = h;
break;
}
}
}
//todo y1 and the others can be undefined if no pixel is found.// y2for(y = h - 1; y > y1; y--) {
for(x = 0; x < w; x++) {
if (data[y * w + x] & 0xff000000) {
y2 = y;
y = 0;
break;
}
}
}
// x1for(y = y1; y < y2; y++) {
for(x = 0; x < w; x++) {
if (x < x1 && data[y * w + x] & 0xff000000) {
x1 = x;
break;
}
}
}
// x2for(y = y1; y < y2; y++) {
for(x = w - 1; x > x1; x--) {
if (x > x2 && data[y * w + x] & 0xff000000) {
x2 = x;
break;
}
}
}
// mark area:
ctx.strokeStyle = "hsl(" + (360 * Math.random()) + ", 80%, 50%)";
ctx.strokeRect(x1 + 0.5, y1 + 0.5, x2 - x1, y2 - y1);
}
body {background:#aaa;margin:1px0}
canvas {border:1px solid #777; background:#f0f0f2}
<button>Again</button><br><canvaswidth=640height=165></canvas>
Post a Comment for "Draw A Box Around Canvas Getimagedata"