将图像裁剪成不规则形状并拉伸

Pio*_*rek 5 javascript html5 html5-canvas

我找到的图像描绘了我的问题:

在此输入图像描述

在此输入图像描述

用户可以在画布上选择四个点来裁剪图像的一部分而不是拉伸它.

如何在HTML5中做到这一点?drawImage函数(据我所知)仅适用于矩形(取x,y,宽度和高度值),因此我不能使用不规则形状.解决方案必须适用于每个现代浏览器,因此我不希望基于webgl或其他东西的东西.

编辑: 更多信息:这将是用于编辑图片的应用程序.我想让用户剪掉更大图片的某些部分并进行编辑.它类似于Paint,因此需要canvas来编辑像素.

Gam*_*ist 0

所以这里有一个绝招:你可以使用 context2d 的常规 drawImage 在三角形内绘制纹理。
\n约束是纹理坐标必须轴对齐。

\n\n

要绘制纹理三角形,您必须:
\n\xe2\x80\xa2 自行计算绘制图像所需的变换。
\n\xe2\x80\xa2 剪切为三角形,因为 drawImage 会绘制四边形。
\n\xe2\x80\xa2 使用正确的变换绘制图像。

\n\n

所以我们的想法是将四边形分成两个三角形,然后渲染两个三角形。

\n\n

但还有一个技巧:在绘制右下三角形时,纹理读取应该从纹理的右下部分开始,然后向上和向左移动。这在 Firefox 中无法完成,因为它只接受 drawImage 的正参数。因此,我计算第一个点与其他两个点的“镜像”,并且我可以再次沿常规方向绘制 - 剪切将确保只绘制正确的部分 - 。

\n\n

小提琴在这里:

\n\n

http://jsfiddle.net/gamealchemist/zch3gdrx/

\n\n

在此输入图像描述

\n\n
function rasterizeTriangle(v1, v2, v3, mirror) {\n    var fv1 = {\n        x: 0,\n        y: 0,\n        u: 0,\n        v: 0\n    };\n    fv1.x = v1.x;\n    fv1.y = v1.y;\n    fv1.u = v1.u;\n    fv1.v = v1.v;\n    ctx.save();\n    // Clip to draw only the triangle\n    ctx.beginPath();\n    ctx.moveTo(v1.x, v1.y);\n    ctx.lineTo(v2.x, v2.y);\n    ctx.lineTo(v3.x, v3.y);\n    ctx.clip();\n    // compute mirror point and flip texture coordinates for lower-right triangle\n    if (mirror) {\n        fv1.x = fv1.x + (v3.x - v1.x) + (v2.x - v1.x);\n        fv1.y = fv1.y + (v3.y - v1.y) + (v2.y - v1.y);\n        fv1.u = v3.u;\n        fv1.v = v2.v;\n    }\n    // \n    var angleX = Math.atan2(v2.y - fv1.y, v2.x - fv1.x);\n    var angleY = Math.atan2(v3.y - fv1.y, v3.x - fv1.x);\n    var scaleX = lengthP(fv1, v2);\n    var scaleY = lengthP(fv1, v3);\n    var cos = Math.cos,\n        sin = Math.sin;\n    // ----------------------------------------\n    //     Transforms\n    // ----------------------------------------\n    // projection matrix (world relative to center => screen)\n    var transfMatrix = [];\n    transfMatrix[0] = cos(angleX) * scaleX;\n    transfMatrix[1] = sin(angleX) * scaleX;\n    transfMatrix[2] = cos(angleY) * scaleY;\n    transfMatrix[3] = sin(angleY) * scaleY;\n    transfMatrix[4] = fv1.x;\n    transfMatrix[5] = fv1.y;\n    ctx.setTransform.apply(ctx, transfMatrix);\n    // !! draw !!\n    ctx.drawImage(bunny, fv1.u, fv1.v, v2.u - fv1.u, v3.v - fv1.v,\n    0, 0, 1, 1);\n    //\n    ctx.restore();\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:我添加了@szym的相关评论,以及他的示例图片:

\n\n
\n

这看起来似乎是正确的。如果原始图像中有任何直线,您将看到每个三角形都有不同的扭曲(2 个不同的仿射变换而不是透视变换)。

\n
\n\n

在此输入图像描述

\n