html5 Canvas的getImageData或toDataURL方法,哪个占用更多内存?

28

我的应用程序的一部分包括使用标准2D上下文画布和WebGL进行HTML5照片编辑。

无论如何,在用户操作他们的照片时,我会保存“撤销”状态。所有这些都存储在Javascript对象中,作为base64图像数据。

一切都运行良好,性能也很好。

但是,我想知道是否从getImageData()中存储数据会占用更少的内存或提供更好的性能?

因此,总结我的问题是:

在内存中哪个占用更多空间,由toDataURL()生成的base64 JPEG还是getImageData()的结果?两者之间是否存在任何性能差异(涉及加载到画布上以及从画布上获取数据)?

提前感谢。

3个回答

30

getImageData() 的内存占用比 toDataURL() 更大。

  • ImageData 是像素数组,是关于图像的最大信息,在像素数组长度上的计算公式为 widthOfImage * heightOfImage * 4。例如,一个尺寸为100的图像的imageData 长度为 var imageDataArrayLenth = 100 * 100 * 4 = 40 000 (bytes);
  • BLOB (JPG 或 PNG) 是压缩使用 JPG 或 PNG 算法的 imageData,可以比 imageData 小 10 到 20 倍(取决于图像内容)。
  • DataURL (BASE64) 是将 imageData 压缩为 JPG 或 PNG,然后转换为字符串,而该字符串比 BLOB 大 37% (info)。

结论:更好的方式是使用BLOB (info)。

//Example of using blob with objectURL
var canvas = document.getElementById("canvas");

canvas.toBlob((blob) => {
  let img = new Image();
  img.onload = () =>  URL.revokeObjectURL(img.src);  // no longer need to read the blob so it's revoked
  img.src = URL.createObjectURL(blob);
  document.body.appendChild(img);
});

12

很好的问题!我不确定对象本身的真实大小,而且在JS的不同实现中可能会有所不同,但这并不意味着我们不能做出一些合理的猜测。

首先,我们可以使用来自此问题的近似函数:JavaScript object size

并制作一个示例:http://jsfiddle.net/g39uz/

字符串大小可能为80116字节,相比之下,ImageData的大小为720056字节。大约如此。

这里有一个数量级的差异,如果图像很简单,差异将更加明显。值得记住的是Base64表示法可以被压缩(确实被压缩了)。让我们暂时将其推向极限,使用空白画布:

http://jsfiddle.net/g39uz/2/

在空白画布上,dataURL字符串只有1996字节左右,但图像数据,当然仍然忠实地描述了每个像素的详细数组,仍然是720056。

简而言之,如果您要存储它,base64字符串可能会占用更少的空间。几个数量级。


4
常见的权衡是 - 为了大量存储空间,你会获得更长的处理时间。我刚完成一个项目,其中我缓存了一张单独的图片(大约600x500像素)。我首先使用toDataURL方法进行缓存,它很小 - 但是将new Image().src设置为URL字符串后,我的帧速率下降了三分之一。在我的情况下,为了提高速度,值得牺牲一些内存。 - Scott Mermelstein

1

我前几天也遇到了这个问题... getImageData方法返回一个图像对象,其中实际数据存储在uint8array中...你必须将数据转换为数据库可以管理的格式,但这并不值得,最终输出比toDataURL方法大得多

将base64字符串重新加载到画布上也非常简单...只需实例化一个新图像,并将src设置为base64字符串即可


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接