Javascript 我应该使用哪个函数。toDataURL()或.toBlob()?

Javascript 我应该使用哪个函数。toDataURL()或.toBlob()?,javascript,canvas,html5-canvas,Javascript,Canvas,Html5 Canvas,我想使用JavaScript在客户端调整图像大小。我找到了两种解决方案,一种是使用.toDataURL()函数,另一种是使用.toBlob()函数。两种解决方案都有效。我只是想知道这两个函数有什么区别?哪一个更好?或者何时应该使用.toDataURL()函数或.toBlob()函数 这是我用来输出这两个函数的代码,我得到的图像大小(字节)和图像颜色(我不确定这一个)略有不同。代码有问题吗 <html> <head> <title>Php

我想使用JavaScript在客户端调整图像大小。我找到了两种解决方案,一种是使用
.toDataURL()
函数,另一种是使用
.toBlob()
函数。两种解决方案都有效。我只是想知道这两个函数有什么区别?哪一个更好?或者何时应该使用
.toDataURL()
函数或
.toBlob()
函数

这是我用来输出这两个函数的代码,我得到的图像大小(字节)和图像颜色(我不确定这一个)略有不同。代码有问题吗

<html>
    <head>
        <title>Php code compress the image</title>
    </head>
    <body>
        <input id="file" type="file" onchange="fileInfo();"><br>
        <div>
            <h3>Original Image</h3>
            <img id="source_image"/>
            <button onclick="resizeImage()">Resize Image</button>
            <button onclick="compressImage()">Compress Image</button>
            <h1 id="source_image_size"></h1>
        </div>
        <div>
            <h3>Resized Image</h3>
            <h1> image from dataURL function </h1>
            <img id="result_resize_image_dataURL"/>

            <h1> image from toBlob function </h1>
            <img id="result_resize_image_toBlob"/>
        </div>
        <div>
            <fieldset>
                <legend>Console output</legend>
                <div id='console_out'></div>
            </fieldset>
        </div>

        <script>
            //Console logging (html)
            if (!window.console)
            console = {};

            var console_out = document.getElementById('console_out');
            var output_format = "jpg";

            console.log = function(message) {
                console_out.innerHTML += message + '<br />';
                console_out.scrollTop = console_out.scrollHeight;
            }

            var encodeButton = document.getElementById('jpeg_encode_button');
            var encodeQuality = document.getElementById('jpeg_encode_quality');

            function fileInfo(){
                var preview = document.getElementById('source_image');
                var file   = document.querySelector('input[type=file]').files[0];
                var reader  = new FileReader();
                reader.addEventListener("load", function(e) {
                    preview.src = e.target.result;
                }, false);
                if (file) {
                    reader.readAsDataURL(file);
                }
            }
            function resizeImage() {
                var loadedData = document.getElementById('source_image');
                var result_image = document.getElementById('result_resize_image_dataURL');

                var cvs = document.createElement('canvas'),ctx;
                cvs.width = Math.round(loadedData.width/4);
                cvs.height = Math.round(loadedData.height/4);
                var ctx = cvs.getContext("2d").drawImage(loadedData, 0, 0, cvs.width, cvs.height);
                cvs.toBlob(function(blob) {
                    var newImg = document.getElementById('result_resize_image_toBlob'),
                        url = URL.createObjectURL(blob);
                    newImg.onload = function() {
                        // no longer need to read the blob so it's revoked
                        URL.revokeObjectURL(url);
                    };

                    newImg.src = url;
                    console.log(blob.size/1024);
                }, 'image/jpeg', 0.92);

                var newImageData = cvs.toDataURL('image/jpeg', 0.92);
                var result_image_obj = new Image();
                result_image_obj.src = newImageData;
                result_image.src = result_image_obj.src;
                var head = 'data:image/png;base64,';
                var imgFileSize = ((newImageData.length - head.length)*3/4)/1024;
                console.log(imgFileSize);
            }

Php代码压缩图像

原始图像 编辑:

根据,它说,

DataURL(BASE64)是将imageData压缩为JPG或PNG,然后转换为字符串,此字符串比BLOB大37%(信息)


字符串是什么意思?它与字节大小相同吗?使用上面提供的代码,大小差异小于1Kb(小于1%)。
.toBlob()
是否总是优于
.toDataURL()
函数?或者有一个特定的条件,使用
.toDataURL()
函数更好?

一定要使用
toBlob()

toDataURL
实际上只是规范中的一个早期错误,如果几个月后定义它,它肯定不会再出现在这里,因为我们可以使用
toBlob
做同样的事情,但会更好

toDataURL()
是同步的,在执行不同的操作时会阻止用户界面
  • 将位图从GPU移动到CPU
  • 转换为图像格式
  • 转换为base64字符串
另一方面,
toBlob()
将仅同步执行第一个项目符号,但将以非阻塞方式转换为图像格式。而且,它不会执行第三个项目符号。
因此,在原始操作中,这意味着
toBlob()
以更好的方式做得更少

toDataURL
结果占用的内存比
toBlob
多。
toDataURL
返回的数据URL是一个,其中包含在base64中压缩的完整二进制数据。
正如您在问题中引用的那样,base64编码本身意味着二进制数据现在将增加约37%。但在这里,它不仅编码为base64,而且使用UTF-16编码存储,这意味着每个ascii字符将占用原始ascii文本所需内存的两倍,我们跳转到一个比原始二进制数据大174%的文件…
而且还没有结束。。。每次在某处使用此字符串时,例如作为DOM元素*的
src
,或通过网络请求发送时,此字符串可以再次在内存中重新分配。
*尽管现代浏览器似乎有处理这种情况的机制

您(几乎)不需要数据url。 使用数据url所能做的一切,都可以使用Blob和Blob URI做得更好

要显示或本地链接到二进制数据(例如供用户下载),请使用Blob URI,使用
URL.createObjectURL()
方法。
它只是指向Blob本身指向的内存中二进制数据的指针。这意味着您可以根据需要多次复制blob URI,它将始终是一个约100个字符的UTF-16字符串,并且二进制数据不会移动

如果您希望将二进制数据发送到服务器,或通过

如果希望将其保存在本地,请使用,它可以保存二进制文件。在LocalStorage中存储二进制文件是一个非常糟糕的主意,因为每次加载页面时都必须加载存储对象


您可能需要数据URL的唯一情况是,如果您希望创建需要嵌入二进制数据的独立文档,在当前文档死后可以访问。但即使如此,要从画布创建图像的数据url版本,请使用一个将
canvas.toBlob()
返回的Blob传递到的url。这将有助于实现完全的异步转换,避免您的用户界面因为没有好的理由而被阻塞。

堆栈溢出的可能副本会尽力让事情尽可能没有意见,所以没有人(希望)会告诉您哪一个“更好”。这两种功能都有各自的用途——根据您的具体情况,由您决定哪一种更合适。@我不同意,在这种情况下,有一个明确的“更好”选项。toDataURL没有toBlob没有的用途。这有点像“我应该使用或css来居中我的元素”之类的问题,除了toDataURL没有官方的反对消息,因为它不幸被广泛使用…@kaido它不像
与css,因为
toDataURL
toBlob
都是在HTML 5中定义的,不是HTML中的一个,而是CSS中的一个。但要说清楚;我们不应该投票决定哪一个更好,而应该陈述事实,读者可以从中得出自己的结论。你的答案几乎就是这样。如果引用“规范中的早期错误”之类的断言会更好,考虑到事实是,已经有人讨论过甚至取代
toBlob
,以支持基于承诺的asBlob或convertToBlob,因为后者在CreencaNVA上可用。但是,不,没有计划从规范中删除它,正如我所说的,它的使用真的太广泛了,现在没有办法回来,但是也没有理由在新的应用中使用它。附言:w3c的定义不再被遵循了,没有其他人理解html5.x这样的东西。你应该阅读whatwg(也将持续下去)。这是一个极好的答案。非常感谢您的详细解释。在什么情况下,dataURL是合理的?相关问题:我们使用base64存储操纵图形的历史状态,但是