html5 canvas.toDataURL output size bigger than original image size

i've just try to resize image in javascript before upload using canvas. I follow the instruction here: https://hacks.mozilla.org/2011/01/how-to-develop-a-html5-image-uploader/.

When I scale the image to 1, which mean, follow the original width and height, the output size of the image is almost double the size of original image. Before that, when I readDataAsURL using FileReader, the output string length is bigger than the image size. How to use html canvas and FileReader correctly?

Thank you.

Upvotes: 2

Views: 5640

Answers (1)

user1693593
user1693593

Reputation:

You could consider using Blobs instead. Data-URI in the browser uses Base-64 encoding which increase the size by 33%, and some change in form of a data-uri header.

To use blobs instead you will need to have in mind that the code becomes asynchronous. Also, there are no guarantee that the resulting image is smaller than the original due to the simple fact that the exported image from the browser is always in RGBA format, while the original PNG source image can be indexed, gray-scale, RGB only, have better compression and so forth.

In the case of FileReader you can use the File object directly with createObjectURL() bypassing the use of FileReader. A File object is basically a Blob with some extended information such as file name etc.

Example Reading Blob/File wo/FileReader

This assumes the input field uses changeHandler below to handle the event (and this example only handles a single file):

function changeHandler() {
  var img = new Image();
  img.onload = drawImageToCanvas;
  img.src = (URL || webkitURL).createObjectURL(this.files[0]);
}

function drawImageToCanvas() {
  // modify canvas size here if needed
  ctx.drawImage(this, 0, 0);  // draw image to canvas
  // since we're async., continue from here (or use promises)
}

Example Blob Export (toBlob)

Exporting using blob:

canvas.toBlob(function(blob) {
  // blob now contains the PNG file
  // This code is called asynchronous, so continue from here.
}, "image/png");

You can now upload the blob instead which will be smaller compared to a Data-URL.

Some browsers may need a polyfill for toBlob() (or simply do a feature detect and use toDataURL() as a fallback in those browsers).

Upvotes: 3

Related Questions