最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to get a rotated crop of an image with HTML canvas - Stack Overflow

programmeradmin1浏览0评论

I have a large canvas containing an image, as shown in the example below:

I have the position and rotation angle of the red rectangle:

red : {
  top : top,
  left : left,
  width : width,
  height : height,
  angle : angle
}

I also have a full set of translated coordinates denoting the actual corner points of the red rotated rectangle.

Finally, I have the position of the blue rectangle relative to the red rectangle:

blue : {
  left : left,
  top : top,
  width : width,
  height : height
}

What I need to do is create a new canvas that is the size of the blue rectangle. The new canvas should contain the correctly rotated portion of the image that is contained within the blue rectangle. The resulting image should look like this:

Here is my JavaScript code so far:

var c = getCenterPoint(); // returns center x/y positions of the RED rectangle
canvas.width = blue.width;
canvas.height = blue.height;
var blueX = red.left + blue.left;
var blueY = red.top + blue.top;
var tx = blueX - c.x;
var ty = blueY - c.y;

this.cursorContext.translate(tx, ty);
this.cursorContext.rotate(angle * (Math.PI / 180));
this.cursorContext.translate(-tx, -ty);

this.cursorContext.drawImage(image, -blueX, -blueY, blue.width, blue.height);

The problem I am having is getting the correct portion of the image when the rectangle is rotated. How can I do this?

I have a large canvas containing an image, as shown in the example below:

I have the position and rotation angle of the red rectangle:

red : {
  top : top,
  left : left,
  width : width,
  height : height,
  angle : angle
}

I also have a full set of translated coordinates denoting the actual corner points of the red rotated rectangle.

Finally, I have the position of the blue rectangle relative to the red rectangle:

blue : {
  left : left,
  top : top,
  width : width,
  height : height
}

What I need to do is create a new canvas that is the size of the blue rectangle. The new canvas should contain the correctly rotated portion of the image that is contained within the blue rectangle. The resulting image should look like this:

Here is my JavaScript code so far:

var c = getCenterPoint(); // returns center x/y positions of the RED rectangle
canvas.width = blue.width;
canvas.height = blue.height;
var blueX = red.left + blue.left;
var blueY = red.top + blue.top;
var tx = blueX - c.x;
var ty = blueY - c.y;

this.cursorContext.translate(tx, ty);
this.cursorContext.rotate(angle * (Math.PI / 180));
this.cursorContext.translate(-tx, -ty);

this.cursorContext.drawImage(image, -blueX, -blueY, blue.width, blue.height);

The problem I am having is getting the correct portion of the image when the rectangle is rotated. How can I do this?

Share Improve this question edited Dec 23, 2022 at 17:25 mfluehr 3,2172 gold badges28 silver badges36 bronze badges asked Jan 14, 2014 at 23:55 GordoGordo 78911 silver badges22 bronze badges 1
  • Could you share the relevant code you have tried with? – user1693593 Commented Jan 15, 2014 at 0:24
Add a ment  | 

1 Answer 1

Reset to default 8

You can use a temporary canvas to clip and unrotate your blue box

  • Clip the boundingbox of the blue rectangle from the image

  • Unrotate the boundingbox so the blue rectangle is unrotated (angle==0)

  • Clip the extra boundingbox area away to reveal only the blue rectangle

  • Draw the blue rectangle to the display canvas

Here’s code and a Demo: http://jsfiddle/m1erickson/28EkG/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery./jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

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

    // blue rect's info

    var blueX=421;
    var blueY=343;
    var blueWidth=81;
    var blueHeight=44;
    var blueAngle=-25.00*Math.PI/180;

    // load the image

    var img=new Image();
    img.onload=start;
    img.src="https://dl.dropboxusercontent./u/139992952/stackoverflow/temp6.jpg";

    function start(){

        // create 2 temporary canvases

        var canvas1=document.createElement("canvas");
        var ctx1=canvas1.getContext("2d");
        var canvas2=document.createElement("canvas");
        var ctx2=canvas2.getContext("2d");

        // get the boundingbox of the rotated blue box

        var rectBB=getRotatedRectBB(blueX,blueY,blueWidth,blueHeight,blueAngle);

        // clip the boundingbox of the rotated blue rect
        // to a temporary canvas

        canvas1.width=canvas2.width=rectBB.width;
        canvas1.height=canvas2.height=rectBB.height;

        ctx1.drawImage(img,
            rectBB.cx-rectBB.width/2,
            rectBB.cy-rectBB.height/2,
            rectBB.width,
            rectBB.height,
            0,0,rectBB.width,rectBB.height
        );

        // unrotate the blue rect on the temporary canvas

        ctx2.translate(canvas1.width/2,canvas1.height/2);
        ctx2.rotate(-blueAngle);
        ctx2.drawImage(canvas1,-canvas1.width/2,-canvas1.height/2);

        // draw the blue rect to the display canvas

        var offX=rectBB.width/2-blueWidth/2;
        var offY=rectBB.height/2-blueHeight/2;

        canvas.width=blueWidth;
        canvas.height=blueHeight;
        ctx.drawImage(canvas2,-offX,-offY);

    }  // end start



    // Utility: get bounding box of rotated rectangle

    function getRotatedRectBB(x,y,width,height,rAngle){
        var absCos=Math.abs(Math.cos(rAngle));
        var absSin=Math.abs(Math.sin(rAngle));
        var cx=x+width/2*Math.cos(rAngle)-height/2*Math.sin(rAngle);
        var cy=y+width/2*Math.sin(rAngle)+height/2*Math.cos(rAngle); 
        var w=width*absCos+height*absSin;
        var h=width*absSin+height*absCos;
        return({cx:cx,cy:cy,width:w,height:h});
    }


}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
发布评论

评论列表(0)

  1. 暂无评论