使用html5画布在非矩形形状和转换中剪切图像 [英] Cropping images with html5 canvas in a non-rectangular shape and transforming

查看:195
本文介绍了使用html5画布在非矩形形状和转换中剪切图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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





  • 剪切图片后,应将图片转换为矩形。

  • 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. 创建第二个目标画布,

    2. 计算将第一个扭曲三角形映射到第二个三角形所需的变换矩阵。
    3. 一个未扭曲的三角形。变换矩阵使用它的工具(缩放,旋转,倾斜,移动)从变形的源三角形中取出每个像素,并将该像素变换到未扭曲的目标三角形。

    4. 将源图像绘制到目标画布上。因为目标画布具有定义的剪切区域,所以图像将仅被绘制到该剪切区域中。由于目标画布已应用了转换,因此先前变形的三角形将以非曲线形式绘制。

    5. 对第二个变形三角形重复步骤#3-5。

    因此,您扭曲的图片(在左侧)可以展开(如右图所示) :



    >



    这是两个未扭曲的三角形在它们拼接在一起形成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.

    • 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.

    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:

    1. Create a second destination canvas to hold your straightened, unwarped image.
    2. Divide the warped, 4-sided polygon into 2 triangles.
    3. 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.
    4. Clip the destination canvas to draw only in the calculated destination triangle.
    5. 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.
    6. Repeat steps #3-5 for the second warped triangle.

    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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆