0

How to convert contents of a large Canvas to a JPEG format? I have a large canvas (around 1000x1000 pixels or larger) that I'd like to convert to JPEG formatted data for uploading to a server.

If the image were smaller, I could use canvas.toDataURL('image/jpeg'), but data URLs have a max size, and my image doesn't fit under that limit.

There is canvas.getImageData() which looks promising, but how to convert that to a JPEG? Is that possible on the client side?

I have tried using canvas.toDataURL(), and it doesn't work for large Canvases. Browsers seem to have max size for dataUrl. For example Chrome gives me data URL data:, when using a large canvas.

Juha Syrjälä
  • 33,425
  • 31
  • 131
  • 183
  • `but data URLs have a max size, and my image doesn't fit under that limit.` which limit are you specifically referring to? and which browser has the issue? A dataURL is a string ... is the limit reached when you create the dataURL? or have you not even tried? – Jaromanda X Jun 14 '18 at 08:42
  • Have you checked [this](https://stackoverflow.com/questions/12796513/html5-canvas-to-png-file)? – Sangbok Lee Jun 14 '18 at 08:49
  • Possible duplicate of [HTML5 Canvas to PNG File](https://stackoverflow.com/questions/12796513/html5-canvas-to-png-file) – Sangbok Lee Jun 14 '18 at 08:49
  • @SangbokLee - your link deals with displaying a dataurl - OP doesn't need to do that – Jaromanda X Jun 14 '18 at 08:50
  • I have tried to use toDataUrl(), it doesn't work if the canvas is too large. For example Chrome truncates the url silently to `data:,`. The max dataUrl length seems to be browser specific https://stackoverflow.com/questions/695151/data-protocol-url-size-limitations – Juha Syrjälä Jun 14 '18 at 09:19
  • No and no, the only limitations for a dataURL are the String max-length and in some browsers, an url max-size **which only concerns the address-bar**. Every browser is well able to display far bigger images in dataURL than what the [canvas is even able to support](http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element). And passed beyond these limits, it's not only the export method that won't work, but actually nothing will. Also, I suspect your Chrome issue is more that you did set either your canvas width or its height to `0`. – Kaiido Jun 14 '18 at 11:39

1 Answers1

4

You can use toBlob to achieve this

The HTMLCanvasElement.toBlob() method creates a Blob object representing the image contained in the canvas; this file may be cached on the disk or stored in memory at the discretion of the user agent.

You'll notice the last two arguments I submitted were 'image/jpeg', 0.9 this is the type and quality you can leave these out if you ever want a PNG.

If type is not specified, the image type is image/png. The created image is in a resolution of 96dpi. The third argument is used with image/jpeg images to specify the quality of the output.

let canvas = document.querySelector('canvas');
ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(600, 0);
ctx.lineTo(1200, 1200);
ctx.lineTo(0, 1200);
ctx.closePath();
ctx.fillStyle = 'yellow';
ctx.fill();

canvas.toBlob((blob) => {
  let img = document.createElement('img');
  let url = URL.createObjectURL(blob);

  img.src = url;
  document.body.appendChild(img);
}, 'image/jpeg', 0.9);
<canvas width="1200" height="1200"></canvas>

I hope you find this helpful

Andrew Bone
  • 7,092
  • 2
  • 18
  • 33
  • You can send the blob to the server rather than appending it, can't you? I just didn't know what method they were using to send things upstream. – Andrew Bone Jun 14 '18 at 09:05
  • toBlob is indeed a better way than toDataURL, but I fear this won't solve OP's problem, they will just get an empty Blob in the same conditions they got `"data:,"` – Kaiido Jun 14 '18 at 11:47