javascript Canvas toDataUrl 增加图像的文件大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9773154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 07:47:58  来源:igfitidea点击:

Canvas toDataUrl increases file size of image

javascriptcanvasdata-url

提问by Lishamatish

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.

当使用 toDataUrl() 设置图像标签的来源时,我发现保存的图像比原始图像大得多。

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.

在下面的示例中,我没有为 toDataUrl 函数指定第二个参数,因此使用的是默认质量。这导致图像比原始图像尺寸大得多。当为全质量指定 1 时,生成的图像更大。

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

谢谢: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.

这是一个例子,不幸的是图像不能跨域,所以我只需要拉一个 jsfiddle 图像。

http://jsfiddle.net/ptSUd/

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.

图像为 7.4kb,如果您随后保存正在输出的图像,您将看到它为 10kb。图像越详细,差异就越明显。如果将 toDataUrl 质量设置为 1,则图像大小为 17kb。

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

我也为此使用了 FireFox 10,当使用 Chrome 时,图像尺寸仍然更大,但没有那么多。

采纳答案by Rob W

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

toDataURL()方法返回的字符串不代表原始数据。

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

我刚刚进行了一些广泛的测试,结果表明创建的 data-URL 取决于浏览器(而不是操作系统)。

 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:

获取 data-URI 的方法无关紧要,以下代码段用于验证文件上传的 data-URI 是否也不同:

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

测试用例: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>

回答by robertc

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 canvasall you have are pixels, you no longer have the original image. toDataURLdoes 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.

图像的大小主要取决于浏览器内置编码器的质量。它与原始图像的大小关系不大。一旦你把任何东西canvas都画在一个只有像素的地方,你就不再拥有原始图像了。 toDataURL不会神奇地重建绘制在canvas. 如果您想要一个与原始图像大小相同的文件:使用原始图像。

回答by Jesse Adamson

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

看起来像 kirilloid 和 Rob 把它钉住了。我也有这个问题,它似乎是一个组合:

  • the dataURL uses base64 encoding which makes it around 1.37 X larger
  • each browser processes the toDataURL function differently
  • dataURL 使用 base64 编码,使其大 1.37 倍左右
  • 每个浏览器对 toDataURL 函数的处理方式不同

base64 encoded image size

base64 编码的图像大小

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

我在 win8.1 firefox 和 chrome 中测试了我的缩略图生成器并获得了 dataURL 字符串大小:

  • firefox = 3.72kB
  • chrome = 3.24kB
  • 火狐 = 3.72kB
  • 铬 = 3.24kB

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

转换为 dataURL 时,我的原始图像从 32kB 变为 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).

我认为 base64 部分是更大的因素,所以我想我现在的计划是将 dataURL 转换回二进制字节数组,然后再将其存储在服务器上(可能在客户端,因为我的服务器很懒惰)。