Rotate image before upload with hidden canvas

I’m trying to rotate my image before uploading.

I tried to create a canvas over the air, rotate it, and get the data inside, but it not seems to works, here is a fiddle:

function rotate() {
    const img = document.getElementById("image");
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  context.rotate(90 * Math.PI / 180);
  context.drawImage(img,0,0);
  img.src = canvas.toDataURL();
  }
<img src="https://lh3.googleusercontent.com/proxy/YhFwjEreTxLoYxYc2sG_VJIp9L03YZAtQZ7FXvI46-NqSyql-rfiaLkN4G8h3Pg7fYwIYuROEBC5pBRnZPnXbgQpmB_qmCjscZ8WYKZ7Xq5j86cZRegymf_tmo2T5VdiZ-2Mfd8tXYnZXuSRh0eDBs537cmZtENW7XjLH5515uYATw" style="width: 100%; height: auto" id="image"/>
<button onclick="rotate()">
Rotate
</button>

Don’t take into account the security error.

I was wondering if it’s the good way to achieve that, if not, how can I do that without any library?

Answer

There are a couple of things you need to do that weren’t in your original code:

  1. Size the canvas to match the image.
  2. Perform your rotation at the center of the canvas, by using context.translate().

(Note that I’m using a data URI in this demo, to avoid the security error.)

function rotate() {
  const img = document.getElementById("image");
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  
  // Make canvas the same size as img
  const cw = img.naturalHeight;
  const ch = img.naturalWidth;
  canvas.width = cw;
  canvas.height = ch;
  
  // Draw rotated img onto canvas
  context.translate(cw / 2, ch / 2);
  context.rotate(90 * Math.PI / 180);
  context.drawImage(img, -ch / 2, -cw / 2, ch, cw);
  
  // Replace img with canvas contents
  img.src = canvas.toDataURL();
}
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAAAyCAYAAADLLVz8AAABO0lEQVRoge3bQQ7CMAxE0RRxYgSnQHDlsmWBit3xjL2Yv6VNm6cKqQls6/7alzvdxXRYBgS7Truh/Xk7/Hx7vGX3EmnUE/gPL3qMsjGAGZhJiCMAz4BMQWwHRCAmILYCVgB0I7YBVk68E7EFkDHhLkQ5IHOiHYhSQMUE1YgyQOXElNeSAEYnFHlNi77KqRDpgJV42WMViFRABl72HDYiDZCJlz2XiUgBVOBlx2AhlgMq8bJjMRBLATvwsmNWI5YBduJlx65ElL6JKJbj1Uv+MkDlxJTXkgB2bASprkkH7NxFU1ybCjhhC5J9D2X7wtP2a79j3pt/mQBmQDADghkQzIBgBgQzIJgBwQwIZkAwA4IZEMyAYAYEMyCYAcEMCDYO8Gj1eOKq98gn8BfU1C0D/90VzN+BYAZEWmt9ABoSb1fIlzNVAAAAAElFTkSuQmCC" style="width: 100%; max-width: 150px; height: auto" id="image" />
<br />
<button onclick="rotate()">
Rotate
</button>