admin管理员组

文章数量:1252720

When using toDataUrl() to set the source of an image tag I am finding that the image when saved is a great deal larger than the original image.

In the example below I am not specifying a second param for the toDataUrl function so the default quality is being used. This is resulting in an image much larger that the original image size. When specifying 1 for full quality the image generated is even larger.

Does anybody know why this is happening or how I can stop it?

            // create image
            var image = document.createElement('img');

            // set src using remote image location
            image.src = 'test.jpg';

            // wait til it has loaded
            image.onload = function (){

            // set up variables
            var fWidth = image.width;
            var fHeight = image.height;

            // create canvas
            var canvas = document.createElement('canvas');
            canvas.id = 'canvas';
            canvas.width = fWidth;
            canvas.height = fHeight;
            var context = canvas.getContext('2d');

            // draw image to canvas
            context.drawImage(image, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight);

            // get data url 
            dataUrl =  canvas.toDataURL('image/jpeg');

            // this image when saved is much larger than the image loaded in
            document.write('<img src="' + dataUrl + '" />');

            }

Thank you :D

Here is an example, unfortunately the image cannot be cross domain and so I am having to just pull one of the jsfiddle images.

/

The image is 7.4kb, if you then save the image which is being output you will see that it is 10kb. The difference is more noticeable with more detailed images. If you set the toDataUrl quality to 1, the image is then 17kb.

I am also using FireFox 10 for this, when using Chrome the image sizes are still larger but not by as much.

When using toDataUrl() to set the source of an image tag I am finding that the image when saved is a great deal larger than the original image.

In the example below I am not specifying a second param for the toDataUrl function so the default quality is being used. This is resulting in an image much larger that the original image size. When specifying 1 for full quality the image generated is even larger.

Does anybody know why this is happening or how I can stop it?

            // create image
            var image = document.createElement('img');

            // set src using remote image location
            image.src = 'test.jpg';

            // wait til it has loaded
            image.onload = function (){

            // set up variables
            var fWidth = image.width;
            var fHeight = image.height;

            // create canvas
            var canvas = document.createElement('canvas');
            canvas.id = 'canvas';
            canvas.width = fWidth;
            canvas.height = fHeight;
            var context = canvas.getContext('2d');

            // draw image to canvas
            context.drawImage(image, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight);

            // get data url 
            dataUrl =  canvas.toDataURL('image/jpeg');

            // this image when saved is much larger than the image loaded in
            document.write('<img src="' + dataUrl + '" />');

            }

Thank you :D

Here is an example, unfortunately the image cannot be cross domain and so I am having to just pull one of the jsfiddle images.

http://jsfiddle.net/ptSUd/

The image is 7.4kb, if you then save the image which is being output you will see that it is 10kb. The difference is more noticeable with more detailed images. If you set the toDataUrl quality to 1, the image is then 17kb.

I am also using FireFox 10 for this, when using Chrome the image sizes are still larger but not by as much.

Share Improve this question edited Mar 19, 2012 at 17:46 Lishamatish asked Mar 19, 2012 at 15:38 LishamatishLishamatish 5612 gold badges4 silver badges18 bronze badges 5
  • 3 dataUrl is stored in base64 instead of binary (1/3 size increase). Also storing algorithm used in browser may be not as optimal as it was used originally. – kirilloid Commented Mar 19, 2012 at 15:42
  • This only applies to images stored remotely, images loaded using a file input are correctly sized. – Lishamatish Commented Mar 19, 2012 at 16:04
  • Are they the same? Remote images on real sites may be better optimized. – kirilloid Commented Mar 19, 2012 at 16:11
  • I know for a fact that the remote image that I am using as an example is 59kb. After resaving from the image tag generated above the image is said to be 134kb. Saving this 59kb image to my HD and then uploading results i a 59kb image. For some reason when the image is remote it is making the image generated a lot larger. – Lishamatish Commented Mar 19, 2012 at 16:29
  • 1 Very good question since there are so many articles showing how to "downsize" an image on the client before uploading it to a server. Yet, none of the articles I've read mention this data bloating issue. And only after wasting hours on it does one realize that canvas isn't a very good imaging resizing solution. +1 – Yogi Commented May 9, 2019 at 17:45
Add a comment  | 

3 Answers 3

Reset to default 14

The string returned by the toDataURL() method does not represent the original data.

I have just performed some extensive tests, which showed that the created data-URL depends on the browser (not on the operating system).

 Environment             -    md5 sum                       - file size
    Original file        - c9eaf8f2aeb1b383ff2f1c68c0ae1085 - 4776 bytes
WinXP Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Chrome 17.0.963.79 - 94913afdaba3421da6ddad642132354a - 7702 bytes
Linux Firefox 10.0.2     - 4f184006e00a44f6f2dae7ba3982895e - 3909 bytes

The method of getting the data-URI does not matter, the following snippet was used to verify that the data-URI from a file upload are also different:

Test case: http://jsfiddle.net/Fkykx/

<input type="file" id="file"><script>
document.getElementById('file').onchange=function() {
    var filereader = new FileReader();
    filereader.onload = function(event) {
        var img = new Image();
        img.onload = function() {
            var c = document.createElement('canvas'); // Create canvas
            c.width = img.width;
            c.height = img.height;  c.getContext('2d').drawImage(img,0,0,img.width,img.height);
            var toAppend = new Image;
            toAppend.title = 'Imported via upload, drawn in a canvas';
            toAppend.src = c.toDataURL('image/png');
            document.body.appendChild(toAppend);
        }
        img.src = event.target.result; // Set src from upload, original byte sequence
        img.title = 'Imported via file upload';
        document.body.appendChild(img);
    };
    filereader.readAsDataURL(this.files[0]);
}
</script>

The size of the image is determined mostly by the quality of the encoder built into the browser. It has very little to do with the size of the original image. Once you draw anything onto a canvas all you have are pixels, you no longer have the original image. toDataURL does not magically reconstitute an image that was painted onto the canvas. If you want a file with the same size as the original image: use the original image.

Looks like kirilloid and Rob nailed it. I had this issue too and it appears to be a combo:

  • the dataURL uses base64 encoding which makes it around 1.37 X larger
  • each browser processes the toDataURL function differently

base64 encoded image size

I tested my thumbnail generator in win8.1 firefox and chrome and got dataURL string sizes:

  • firefox = 3.72kB
  • chrome = 3.24kB

My original image when converted to dataURL went from 32kB to 45kB.

I think the base64 part is the larger factor so I guess my plan now is to convert the dataURL back to a binary byte array before I store it on the server (probably on the client side because my server's lazy).

本文标签: javascriptCanvas toDataUrl increases file size of imageStack Overflow