使用html5画布在非矩形形状和转换中剪切图像 [英] Cropping images with html5 canvas in a non-rectangular shape and transforming
问题描述
我是html5画布的新手,但我正在创建一个基于html5画布的图像裁剪器,其中包含下一个功能。
- 剪切图片后,应将图片转换为矩形。
- 创建第二个目标画布,
- 计算将第一个扭曲三角形映射到第二个三角形所需的变换矩阵。 一个未扭曲的三角形。变换矩阵使用它的工具(缩放,旋转,倾斜,移动)从变形的源三角形中取出每个像素,并将该像素变换到未扭曲的目标三角形。
- 将源图像绘制到目标画布上。因为目标画布具有定义的剪切区域,所以图像将仅被绘制到该剪切区域中。由于目标画布已应用了转换,因此先前变形的三角形将以非曲线形式绘制。
- 对第二个变形三角形重复步骤#3-5。
- It should crop image in a polygon shape, but doesn't have to be a rectangular.
- After cropping the image, it should transform the image into rectangular shape.
- Create a second destination canvas to hold your straightened, unwarped image.
- Divide the warped, 4-sided polygon into 2 triangles.
- Calculate the transformation matrix needed to map the first warped triangle into an unwarped triangle. A transformation matrix uses it's tools (scaling, rotation, skewing, movement) to take each pixel from the warped source triangle and transform that pixel onto the unwarped destination triangle.
- Clip the destination canvas to draw only in the calculated destination triangle.
- Draw the source image onto the destination canvas. Because the destination canvas has a clipping region defined, the image will only be drawn into that clipping region. Because the destination canvas has a transformation applied to it, the previously warped triangle will be draw as unwarped.
- Repeat steps #3-5 for the second warped triangle.
ul>
我试图搜索满足这些功能但没有找到任何图片的任何图片裁剪器。
可以管理调整大小处理程序和裁剪的东西,但我不知道变换裁剪的图像。
有没有很好的例子或图书馆来做这个?
我添加图片来清除。
当您裁剪第一个图像,结果应该是第二个图像。
ADDED!
我认为@markE的解决方案可以工作,但是在实施和测试一些图片后,它将不能很好地与非平行四边形。
< img src =https://i.stack.imgur.com/bHimA.pngalt =示例1 - cropped>
正如你所看到的,由于这种方法将矩形分割成两个三角形,翘曲的角度和数量?对于两个三角形结束不同。因此,裁剪的图像被显示失真。
你要求的是类似于Photoshop的透视裁剪工具。
这样可以接受未矫直,将其转换为直的,无畸变的图像。
http://www.howtogeek.com/howto/30973/easily-straighten-crooked-photographs-in-photoshop/
左:不直,扭曲的图像,右:拉直,反曲的图像
您可以也可以在html5画布中拉直和解开四边形多边形,如下所示:
因此,您扭曲的图片(在左侧)可以展开(如右图所示) :
>
这是两个未扭曲的三角形在它们拼接在一起形成1个未扭曲的矩形之前的样子:
这里是示例代码和演示:
var canvas = document.getElementById ; var ctx = canvas.getContext(2d); var canvas1 = document.getElementById(canvas1); var ctx1 = canvas1.getContext(2d); // anchorors defined the warped rectanglevar 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} //定义期望未扭曲矩形var的角点= {TL:{x:0,y:0},// r TR:{x:300,y:0} g BR:{x:300,y:300},// b BL:{x:0,y:300},// gold} //加载示例imagevar img = new Image(); img.onload = start; img.src =https://dl.dropboxusercontent.com/u/139992952/multple/skewed1.png; function start(){//设置画布大小等于图像大小cw = canvas.width = canvas1.width = img.width; ch = canvas.height = canvas1.height = img.height; //在源画布上绘制示例图像ctx.drawImage(img,0,0); //清除源矩形并将其绘制到目标画布undarp(anchors,untarped,ctx1);} //重新布置源矩形函数unwarp(anchors,unfarped,context){//清除目标画布context.clearRect 0,context.canvas.width,context.canvas.height); //取消扭曲的多边形的左下三角形mapTriangle(context,anchors.TL,anchors.BR,anchors.BL,unwarped.TL,unwarped.BR,unwarped.BL); //消除三角形之间的微小间隔ctx1.translate(-1,1); //取消扭曲的多边形的右上角三角形mapTriangle(context,anchors.TL,anchors.TR,anchors.BR,unwarped.TL,unwarped.TR,unwarped.BR);} //透视映射:映射扭曲三角形into untarped triangle // Attribution:(SO user:6502),http://stackoverflow.com/questions/4774172/image-manipulation-and-texture-mapping-using-html5-canvas/4774298#4774298function mapTriangle(ctx,p0 ,p1,p2,p_0,p_1,p_2){//断开单独的三角形x的& 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&未转换的目标画布ctx.save(); //将目标画布剪切到未扭曲的目标三角形ctx.beginPath(); ctx.moveTo(x0,y0); ctx.lineTo(x1,y1); ctx.lineTo(x2,y2); ctx.closePath(); ctx.clip(); //计算矩阵变换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 * 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 * //绘制变换后的图像ctx.transform(delta_a / delta,delta_d / delta,delta_b / delta,delta_e / delta,delta_c / delta,delta_f / delta); //将转换后的源图像绘制到目标画布ctx.drawImage(img,0,0); //将上下文恢复为未压缩的未转换状态ctx.restore();}
body {background-color:ivory; } canvas {border:1px solid red;}
h4>将变形的图像变换成未变形的图像。< / h4>< canvas id =canvaswidth = 300 height = 300>< / canvas>< canvas id =canvas1width = 300 height = 300& < / canvas>
I am new to html5 canvas but I am creating a html5 canvas based image cropper which includes next features.
I tried to search any image croppers that satisfies these features, but couldn't find any.
I think I can manage to make the resize handlers and cropping stuff, but I have no idea of transformming the cropped image. Are there any nice examples or libraries to do this?
I am adding images to make things clear. when you crop the first image, the result should be the second image.
ADDED!
I thought @markE 's solution would work, but after implementing and testing some images, I found out that it won't work very well with non-parallelograms.
As you can see, since this approach splits the rectangle into two triangles, the warped angles and amount? ends up different for both triangles. Thus, cropped images are shown distorted. I am figuring other ways to solve it.
What you are asking for is similar to Photoshop's Perspective Crop Tool
.
This allow you to take in an un-straightened, skewed image and convert it into a straight, undistorted image.
http://www.howtogeek.com/howto/30973/easily-straighten-crooked-photographs-in-photoshop/
Left: unstraight, warped image, Right: straightened, unwarped image
You can also straighten and unwarp a 4-sided polygon in html5 canvas like this:
So your warped image (on the left) can be unwarped (as shown on the right):
This is what the 2 unwarped triangles look like before they are stitched together to form 1 unwarped rectangle:
Here is example code and a Demo:
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>
这篇关于使用html5画布在非矩形形状和转换中剪切图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!