mar*_*man 10 javascript canvas html5-canvas
我想在客户端使用 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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
基于html5 Canvas getImageData 或 toDataURL 的结果 - 哪个占用更多内存?,它说
“DataURL (BASE64) 是将 imageData 压缩为 JPG 或 PNG,然后转换为字符串,此字符串比 BLOB 大 37%(信息)。”
字符串是什么意思?它与以字节为单位的大小相同吗?使用我上面提供的代码,大小差异小于 1Kb(小于 1%)。是.toBlob()总是比.toDataURL()功能?或者有一个特定的条件,最好使用.toDataURL()函数?
Kai*_*ido 23
一定要一起去toBlob()。
toDataURL实际上只是规范中的一个早期错误,如果它在几个月后被定义,它肯定不会再出现了,因为我们可以做同样的事情,但使用toBlob.
toDataURL() 是同步的,并且会在执行不同操作时阻塞您的 UItoBlob()另一方面,只会同步执行第一个子弹,但会以非阻塞方式转换为图像格式。此外,它根本不会做第三个子弹。
所以在原始操作中,这意味着toBlob()以更好的方式做更少的事情。
toDataURLresult 比toBlob's占用更多的内存。返回的 data-URLtoDataURL是一个USVString,其中包含以 base64 压缩的完整二进制数据。
正如您问题中的引用所说,base64 编码本身意味着二进制数据现在将大 ~37%。但在这里它不仅编码为 base64,而且使用 UTF-16 编码存储,这意味着每个 ascii 字符将占用原始 ascii 文本所需内存的两倍,并且我们跳转到比原始二进制数据大 174% 的文件。 ..
还没有结束... 每次你在某处使用这个字符串时,例如作为srcDOM 元素*的 ,或者当通过网络请求发送它时,这个字符串可以再次在内存中重新分配。
*虽然现代浏览器似乎有处理这种确切情况的机制
使用 data-url 可以做的所有事情,使用 Blob 和 Blob-URI 也可以做得更好。
要显示或本地链接到二进制数据(例如供用户下载),请使用 Blob-URI,使用URL.createObjectURL()方法。
它只是一个指向 Blob 本身指向的内存中的二进制数据的指针。这意味着您可以根据需要多次复制 blob-URI,它始终是一个 ~100 个字符的 UTF-16 字符串,并且二进制数据不会移动。
如果您希望将二进制数据发送到服务器,请直接将其作为二进制发送,或通过multipart/formdata 请求发送。
如果您希望将其保存在本地,请使用IndexedDB,它能够保存二进制文件。将二进制文件存储在 LocalStorage 中是一个非常糟糕的主意,因为必须在每次页面加载时加载 Storage 对象。
您可能需要 data-urls 的唯一情况是,如果您希望创建需要嵌入二进制数据的独立文档,在当前文档死后可访问。但即便如此,要从画布创建图像的数据 url 版本,请使用FileReader,您会将canvas.toBlob(). 这将实现完整的异步转换,避免您的 UI 无缘无故被阻止。
| 归档时间: |
|
| 查看次数: |
3487 次 |
| 最近记录: |