自动将HTML5画布裁剪为内容

c24*_*24w 23 html javascript html5 html5-canvas

让我们说这是我的画布,上面画着一张邪恶的脸.我想用toDataURL()我的邪恶面孔作为PNG出口; 然而,整个画布都是光栅化的,包括邪恶的脸和画布边缘之间的"空白".

+---------------+
|               |
|               |
|     (.Y. )    |
|      /_       |
|     \____/    |
|               |
|               |
+---------------+
Run Code Online (Sandbox Code Playgroud)

裁剪/修剪/收缩我的画布到其内容的最佳方法是什么,所以我的PNG不比脸部的'边界框'大,如下所示?最好的方法似乎是缩放画布,但假设内容是动态的......?我敢肯定应该有一个简单的解决方案,但它正在逃避我,谷歌搜索.

+------+
|(.Y. )|
| /_   |
|\____/|
+------+
Run Code Online (Sandbox Code Playgroud)

谢谢!

小智 29

function cropImageFromCanvas(ctx, canvas) {

var w = canvas.width,
h = canvas.height,
pix = {x:[], y:[]},
imageData = ctx.getImageData(0,0,canvas.width,canvas.height),
x, y, index;

for (y = 0; y < h; y++) {
    for (x = 0; x < w; x++) {
        index = (y * w + x) * 4;
        if (imageData.data[index+3] > 0) {

            pix.x.push(x);
            pix.y.push(y);

        }   
    }
}
pix.x.sort(function(a,b){return a-b});
pix.y.sort(function(a,b){return a-b});
var n = pix.x.length-1;

w = pix.x[n] - pix.x[0];
h = pix.y[n] - pix.y[0];
var cut = ctx.getImageData(pix.x[0], pix.y[0], w, h);

canvas.width = w;
canvas.height = h;
ctx.putImageData(cut, 0, 0);

var image = canvas.toDataURL();
var win=window.open(image, '_blank');
win.focus();

}
Run Code Online (Sandbox Code Playgroud)

  • 这里不需要排序功能.如果您跟踪像素不透明的最小x,y和最大x,y,则可以完全删除排序. (3认同)
  • 检查 alpha 通道 (`imageData.data[index+3] &gt; 0`) 对我来说不起作用,因为它总是大于 0,必须切换到检查颜色是否不是白色(它适合我的需要,因为我有一个白色背景):`imageData.data[index] != 255 &amp;&amp; imageData.data[index+1] != 255 &amp;&amp; imageData.data[index+2] != 255`。然后裁剪效果很好,谢谢。 (2认同)

Put*_*uko 11

如果我理解得很好,你想要"修剪"你所有的图像/绘图,并将画布调整到那个大小(就像在Photoshop中执行"修剪"命令一样).

我将如何做到这一点.

  1. 运行所有画布像素,检查其alpha分量是否> 0(这意味着在该像素中绘制了某些内容).例如,如果你的画布背景是用纯色填充的,你可以选择检查r,g,b值.

  2. 获取最左侧像素的te坐标非空,对于最右侧的像素,则相同.因此,您将获得包含非空的画布区域的想象"矩形"的坐标.

  3. 存储pixeldata的那个区域.

  4. 将画布调整为新尺寸(我们在步骤2中获得的区域).

  5. 将保存的区域粘贴回画布.

呃,瞧... :)

根据画布的大小,访问pixeldata非常慢(如果它很大,可能需要一段时间).有一些优化可以使用原始画布pixeldata(我想在MDN上有一篇关于这个主题的文章),我建议你去谷歌.

我在jsFiddle中准备了一个小草图,您可以将其用作代码的起点.

在jsFiddle工作样本

希望我帮助过你.
C:.


Kyl*_*yle 8

这是我的看法。我觉得所有其他解决方案都过于复杂。不过,在创建它之后,我现在看到它与其他人的解决方案相同,希望他们只是共享一个小提琴而不是一个函数。

function trimCanvas(canvas){
    const context = canvas.getContext('2d');

    const topLeft = {
        x: canvas.width,
        y: canvas.height,
        update(x,y){
            this.x = Math.min(this.x,x);
            this.y = Math.min(this.y,y);
        }
    };

    const bottomRight = {
        x: 0,
        y: 0,
        update(x,y){
            this.x = Math.max(this.x,x);
            this.y = Math.max(this.y,y);
        }
    };

    const imageData = context.getImageData(0,0,canvas.width,canvas.height);

    for(let x = 0; x < canvas.width; x++){
        for(let y = 0; y < canvas.height; y++){
            const alpha = imageData.data[((y * (canvas.width * 4)) + (x * 4)) + 3];
            if(alpha !== 0){
                topLeft.update(x,y);
                bottomRight.update(x,y);
            }
        }
    }

    const width = bottomRight.x - topLeft.x;
    const height = bottomRight.y - topLeft.y;

    const croppedCanvas = context.getImageData(topLeft.x,topLeft.y,width,height);
    canvas.width = width;
    canvas.height = height;
    context.putImageData(croppedCanvas,0,0);

    return canvas;
}
Run Code Online (Sandbox Code Playgroud)