Distort Image into Isosceles Trapezoid with Canvas
Alexander O'Mara
Recently I wanted to programmatically distort an image into an isosceles trapezoid using JavaScript to get a simple 3D perspective effect. This might seem like a simple task but when you only have 2D rotate and skew transforms, there isn’t a straightforward way to make such a transform.
One option might be to use the 3D transforms of WebGL in a browser, but that’s a really heavy solution and there currently aren’t any WebGL canvas libraries for Node.JS. It would be better if we could use just a 2D canvas drawing context.
So how can we accomplish this without 3D transforms? Read on to find out!
End Result
It’s best begin with the end in mind, and a pictures worth a thousand works, so essentially we’re looking to be able to turn an image like this:
Into an image like this:
First Attempt
In theory, an isosceles trapezoid transform seems simple enough. Take a canvas, make another canvas of equal size, and draw the first canvas to the second canvas row-by-row, calculating the width and x position of each row based on the y position in the image. Let’s try that.
Note: In these examples, I’m using Automattic’s canvas library on NPM, but this can easily be adapted to work in a browser.
Simple enough, just copy and resize row-by-row, making sure to keep in the center.
Easy right? Not on closer inspection…
See that dashed line down the middle? Seems we’re having trouble drawing the image exactly centered. Darn floating point precision errors…
Looks like we’re going to have to find a way around this.
Second Attempt
We can draw to whole integer offsets like x=0 with perfect precision. So let’s split the job in-half, right down the middle, and reflect the left half before and after we skew it.
Comments