gpt4 book ai didi

html - 使用非矩形形状的 html5 Canvas 裁剪图像并进行转换

转载 作者:可可西里 更新时间:2023-11-01 14:45:56 24 4
gpt4 key购买 nike

我是 html5 canvas 的新手,但我正在创建一个基于 html5 canvas 的图像裁剪器,其中包括下一个功能。

  • 它应该以多边形形状裁剪图像,但不一定是矩形。
  • 裁剪图像后,它应该将图像转换为矩形。

我尝试搜索任何满足这些功能的图像裁剪器,但找不到。

我想我可以设法制作调整大小的处理程序和裁剪内容,但我不知道如何转换裁剪后的图像。是否有任何好的示例或库可以执行此操作?


我添加图片是为了让事情更清楚。当您裁剪第一张图片时,结果应该是第二张图片。

selecting cropping area enter image description here


已添加!

我认为@markE 的解决方案可行,但在实现和测试一些图像后,我发现它不适用于非平行四边形。

sample 1 - original sample 1 - cropped

sample 2 - original sample 2 - cropped

如您所见,由于这种方法将矩形拆分为两个三角形,因此扭曲的角度和数量?两个三角形的结果不同。因此,裁剪后的图像显示失真。我正在想办法解决它。

最佳答案

您要求的类似于 Photoshop 的透视裁剪工具

这使您可以接收未拉直、倾斜的图像并将其转换为笔直、未失真的图像。

http://www.howtogeek.com/howto/30973/easily-straighten-crooked-photographs-in-photoshop/

:不直的、扭曲的图像,:拉直的、未扭曲的图像

enter image description here

您还可以像这样在 html5 Canvas 中拉直和展开 4 边多边形:

  1. 创建第二个目标 Canvas 来保存拉直、未变形的图像。
  2. 将扭曲的 4 边多边形分成 2 个三角形。
  3. 计算将第一个变形三角形映射到未变形三角形所需的变换矩阵。转换矩阵使用它的工具(缩放、旋转、倾斜、移动)从变形的源三角形中获取每个像素,并将该像素转换到未变形的目标三角形上。
  4. 剪辑目标 Canvas 以仅在计算出的目标三角形中绘制。
  5. 将源图像绘制到目标 Canvas 上。因为目标 Canvas 定义了裁剪区域,所以图像只会绘制到该裁剪区域中。因为目标 Canvas 应用了变换,所以之前变形的三角形将被绘制为未变形。
  6. 对第二个扭曲的三角形重复步骤#3-5。

因此您的变形图像(在左侧)可以恢复(如右侧所示):

enter image description here

这是 2 个未扭曲的三角形在缝合在一起形成 1 个未扭曲的矩形之前的样子:

enter image description here

这是示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");

// anchors defining the warped rectangle
var anchors={
TL:{x:70,y:40}, // r
TR:{x:377,y:30}, // g
BR:{x:417,y:310}, // b
BL:{x:70,y:335}, // gold
}

// cornerpoints defining the desire unwarped rectangle
var unwarped={
TL:{x:0,y:0}, // r
TR:{x:300,y:0}, // g
BR:{x:300,y:300}, // b
BL:{x:0,y:300}, // gold
}

// load example image
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/skewed1.png";
function start(){

// set canvas sizes equal to image size
cw=canvas.width=canvas1.width=img.width;
ch=canvas.height=canvas1.height=img.height;

// draw the example image on the source canvas
ctx.drawImage(img,0,0);

// unwarp the source rectangle and draw it to the destination canvas
unwarp(anchors,unwarped,ctx1);

}


// unwarp the source rectangle
function unwarp(anchors,unwarped,context){

// clear the destination canvas
context.clearRect(0,0,context.canvas.width,context.canvas.height);

// unwarp the bottom-left triangle of the warped polygon
mapTriangle(context,
anchors.TL, anchors.BR, anchors.BL,
unwarped.TL, unwarped.BR, unwarped.BL
);

// eliminate slight space between triangles
ctx1.translate(-1,1);

// unwarp the top-right triangle of the warped polygon
mapTriangle(context,
anchors.TL, anchors.TR, anchors.BR,
unwarped.TL, unwarped.TR, unwarped.BR
);

}


// Perspective mapping: Map warped triangle into unwarped triangle
// Attribution: (SO user: 6502), http://stackoverflow.com/questions/4774172/image-manipulation-and-texture-mapping-using-html5-canvas/4774298#4774298
function mapTriangle(ctx,p0, p1, p2, p_0, p_1, p_2) {

// break out the individual triangles x's & y's
var x0=p_0.x, y0=p_0.y;
var x1=p_1.x, y1=p_1.y;
var x2=p_2.x, y2=p_2.y;
var u0=p0.x, v0=p0.y;
var u1=p1.x, v1=p1.y;
var u2=p2.x, v2=p2.y;

// save the unclipped & untransformed destination canvas
ctx.save();

// clip the destination canvas to the unwarped destination triangle
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.closePath();
ctx.clip();

// Compute matrix transform
var delta = u0 * v1 + v0 * u2 + u1 * v2 - v1 * u2 - v0 * u1 - u0 * v2;
var delta_a = x0 * v1 + v0 * x2 + x1 * v2 - v1 * x2 - v0 * x1 - x0 * v2;
var delta_b = u0 * x1 + x0 * u2 + u1 * x2 - x1 * u2 - x0 * u1 - u0 * x2;
var delta_c = u0 * v1 * x2 + v0 * x1 * u2 + x0 * u1 * v2 - x0 * v1 * u2 - v0 * u1 * x2 - u0 * x1 * v2;
var delta_d = y0 * v1 + v0 * y2 + y1 * v2 - v1 * y2 - v0 * y1 - y0 * v2;
var delta_e = u0 * y1 + y0 * u2 + u1 * y2 - y1 * u2 - y0 * u1 - u0 * y2;
var delta_f = u0 * v1 * y2 + v0 * y1 * u2 + y0 * u1 * v2 - y0 * v1 * u2 - v0 * u1 * y2 - u0 * y1 * v2;

// Draw the transformed image
ctx.transform(
delta_a / delta, delta_d / delta,
delta_b / delta, delta_e / delta,
delta_c / delta, delta_f / delta
);

// draw the transformed source image to the destination canvas
ctx.drawImage(img,0,0);

// restore the context to it's unclipped untransformed state
ctx.restore();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4>Warped image transformed into an unwarped image.</h4>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="canvas1" width=300 height=300></canvas>

关于html - 使用非矩形形状的 html5 Canvas 裁剪图像并进行转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30565987/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com