Cropping images with html5 canvas in a non-rectangular shape and transforming -
i new html5 canvas creating html5 canvas based image cropper includes next features.
- it should crop image in polygon shape, doesn't have rectangular.
- after cropping image, should transform image rectangular shape.
i tried search image croppers satisfies these features, couldn't find any.
i think can manage make resize handlers , cropping stuff, have no idea of transformming cropped image. there nice examples or libraries this?
i adding images make things clear. when crop first image, result should second image.
added!
i thought @marke 's solution work, after implementing , testing images, found out won't work non-parallelograms.
as can see, since approach splits rectangle 2 triangles, warped angles , amount? ends different both triangles. thus, cropped images shown distorted. figuring other ways solve it.
what asking similar photoshop's perspective crop tool
.
this allow take in un-straightened, skewed image , convert 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 straighten , unwarp 4-sided polygon in html5 canvas this:
- create second destination canvas hold straightened, unwarped image.
- divide warped, 4-sided polygon 2 triangles.
- calculate transformation matrix needed map first warped triangle unwarped triangle. transformation matrix uses it's tools (scaling, rotation, skewing, movement) take each pixel warped source triangle , transform pixel onto unwarped destination triangle.
- clip destination canvas draw in calculated destination triangle.
- draw source image onto destination canvas. because destination canvas has clipping region defined, image drawn clipping region. because destination canvas has transformation applied it, warped triangle draw unwarped.
- repeat steps #3-5 second warped triangle.
so warped image (on left) can unwarped (as shown on right):
this 2 unwarped triangles before stitched form 1 unwarped rectangle:
here example code , demo:
var canvas=document.getelementbyid("canvas"); var ctx=canvas.getcontext("2d"); var canvas1=document.getelementbyid("canvas1"); var ctx1=canvas1.getcontext("2d"); // anchors defining 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 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 image size cw=canvas.width=canvas1.width=img.width; ch=canvas.height=canvas1.height=img.height; // draw example image on source canvas ctx.drawimage(img,0,0); // unwarp source rectangle , draw destination canvas unwarp(anchors,unwarped,ctx1); } // unwarp source rectangle function unwarp(anchors,unwarped,context){ // clear destination canvas context.clearrect(0,0,context.canvas.width,context.canvas.height); // unwarp bottom-left triangle of 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 top-right triangle of warped polygon maptriangle(context, anchors.tl, anchors.tr, anchors.br, unwarped.tl, unwarped.tr, unwarped.br ); } // perspective mapping: map warped triangle 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 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 unclipped & untransformed destination canvas ctx.save(); // clip destination canvas 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 transformed image ctx.transform( delta_a / delta, delta_d / delta, delta_b / delta, delta_e / delta, delta_c / delta, delta_f / delta ); // draw transformed source image destination canvas ctx.drawimage(img,0,0); // restore context it's unclipped untransformed state ctx.restore(); }
body{ background-color: ivory; } canvas{border:1px solid red;}
<h4>warped image transformed unwarped image.</h4> <canvas id="canvas" width=300 height=300></canvas> <canvas id="canvas1" width=300 height=300></canvas>
Comments
Post a Comment