Introduction
I found myself building a website to upload photos. Sometimes the photos needed some rotation. The user could cancel the upload, rotate them locally and restart, but I was trying to find a way to rotate these images, that are usually rectangular, in the same page.
Background
If you need an introduction about HTML5 canvas rotation feature, you can take a look to the following link: http://www.html5canvastutorials.com/advanced/html5-canvas-transform-rotate-tutorial/
Using the code
I start builing a basic html document with an image myImage and a canvas myCanvas elements:
<!DOCTYPE html>
<html>
<body>
<p>Image:</p>
<img id="myImage" width="220" height="277" src="myimage.jpg" alt="myImage">
<p>Canvas:</p>
<canvas id="myCanvas" width="240" height="297" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script> ... </script>
</body>
</html>
In the script, I have the following:
<script>
window.onload = function() {
var c = document.getElementById("myCanvas");
var img = document.getElementById("myImage");
var cnvsSize;
if (img.width > img.height)
{
cnvsSize = img.width;
isHorizontal = true;
}
else
{
cnvsSize = img.height;
isHorizontal = false;
}
c.width=cnvsSize;
c.height= cnvsSize;
var ctx = c.getContext("2d");
ctx.clearRect(0,0,c.width,c.height);
ctx.translate(c.width/2,c.height/2);
ctx.rotate(90*Math.PI/180);
var Y = -cnvsSize/2;
var X = -cnvsSize/2;
if (isHorizontal){
Y = (- img.height)/2;
}
else{
X = (- img.width)/2;
}
ctx.drawImage(img,X,Y);
var imgSquared = new Image();
imgSquared.src = c.toDataURL("image/jpg");
imgSquared.onload = function() {
c.width= img.height;
c.height= img.width;
if (isHorizontal)
{
var sourceX = (cnvsSize - c.width)/2;
var sourceY = 0;
}
else
{
var sourceX = 0;
var sourceY = (cnvsSize - c.height)/2;
}
var sourceWidth = c.width;
var sourceHeight = c.height;
var destX = 0;
var destY = 0;
var destWidth = c.width;
var destHeight = c.height;
ctx.clearRect(0,0,c.width,c.height);
ctx.drawImage(imgSquared,sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
imgSquared = null;
};
}
</script>
So, after retreiving MyCanvas and MyImage from the document, I resize the canvas to be squared taking the bigger size of the image (width or height).
Later, I retrieved the context and clear the whole rectangle (in fact an square) of the canvas.
Next, I translate the (0,0) to the center of the canvas and rotate it.
Next, I calculate where the image should be drawn. By default, it should be minus half of the size of the canvas (considering with are starting from the center of the canvas).
Considering if the image is horizontal or vertical, this coordinates could be smaller to only minus half of the size of the image.
Once calculate the coordinates, the image is drawn.
Next, I create a temporary image to save the square image from the canvas.
In the onload event of this image, the canvas is resize to the dimension expected for the rotated image (width to height and height to width of the original image).
In order to draw the temporary image in the resized canvas, I had to calculate the x, y, width and height of the image source that should be drawn in the x, y, width and height of the destination canvas.
According to the dimension of the image (horizontal or vertical), there is a margin that need to be left from the temporary image. For that I compare the original canvas size with the current size (cnvsSize - c.height)/2.
Finally, the context clear the rectangle of the canvas and the image is drawn again...happyly rotated!!.
Points of Interest
The canvas look powerful, only requires some patient to understand how it works.
History
Keep a running update of any changes or improvements you've made here.