gpt4 book ai didi

javascript - Fabric JS : Performance of very large images (20mb+)

转载 作者:行者123 更新时间:2023-11-29 16:01:10 27 4
gpt4 key购买 nike

我正在使用 Fabric JS 来处理非常大的图像 (20mb+)。我发现与使用标准 Canvas API 相比,Fabric 在处理 Canvas 中的大图像时要慢得多。

下面的代码片段有两个输入按钮,一个使用标准 Canvas API 将图像添加到 Canvas ,另一个使用 Fabric JS。每个方法还会使用 toDataUrl() 将 Canvas 转换为数据 url。每个方法还记录三个时间:开始时间、img.onload 函数完成的时间以及 toDataUrl() 完成的时间。

这是一张表格,比较了我针对不同图像尺寸测试的导入+导出时间: import times for 500kb to 50mb photos

这是一张显示 Fabric 导入+导出时间与 Canvas API 性能的图表:graph

问题:

  • 为什么在 Canvas 上导入和导出大图像时 Fabric 的性能比 Canvas API 慢很多?
  • 在使用大图像时是否有提高 Fabric 性能的方法?
  • 我的测试用例是否准确地代表了 Fabric 的性能?

// Standard Import
function handleFiles(e) {
var t0 = performance.now();
console.log('Standard Import')
console.log('Start Time: ', Math.round(t0/1000))
var promise = new Promise(function(resolve) {
var URL = window.webkitURL || window.URL;
var ctx = document.getElementById('canvas').getContext('2d');
canvas = document.getElementById('canvas');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
resolve("done")
};
img.src = url;
});

promise.then(function(result) {
var t1 = performance.now()
console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
var dataURL = canvas.toDataURL('image/png')
return
}).then(function(result){
t2 = performance.now()
console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
return
});
}

// Fabric Import
function handleFilesFabric(e) {
var t0 = performance.now();
console.log('Fabric Import')
console.log('Start Time: ', Math.round(t0/1000))
var promise = new Promise(function(resolve) {
var canvas = new fabric.Canvas('canvas');
var reader = new FileReader();
reader.onload = function (event){
var imgObj = new Image();
imgObj.src = event.target.result;
imgObj.onload = function () {
var image = new fabric.Image(imgObj);
canvas.setHeight(imgObj.height);
canvas.setWidth(imgObj.width);
canvas.add(image);
canvas.renderAll();
canvas.forEachObject(function(object){
object.selectable = false;
});
resolve("done")
}
}
reader.readAsDataURL(e.target.files[0]);
});

promise.then(function(result) {
var t1 = performance.now()
console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
var dataURL = canvas.toDataURL('image/png')
return
}).then(function(result){
t2 = performance.now()
console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
return
});
}

window.onload = function() {
// Standard Import
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
// Fabric Import
var input2 = document.getElementById('input2');
input2.addEventListener('change', handleFilesFabric, false);
};
canvas {
border: 2px solid;
}
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Upload & Display Image w/ Canvas</title>
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.min.js"></script>
</head>
<body>
<h1> Upload & Display Image</h1>
<canvas width="400" height="400" id="canvas"></canvas>
<br>
<b>Standard Add Image</b><br>
<input type="file" id="input"/>
<br>
<b>Fabric Add Image</b><br>
<input type="file" id="input2"/>
<script src="js/index.js"></script>
</body>
</html>

最佳答案

为了更公平,我稍微重构了代码:加载图像的方式相同,两个事件在 2 个不同的 Canvas 上依次运行。

同时删除对于此测试没有意义的其他 fabricJS 功能。我认为对于更大的图像,差异现在应该更小,您可以在带有大图像的代码段中尝试吗?

顺便说一下,您不能将文件中的 URL.createObjectUrl 与 dataUrl 上的文件读取器进行比较。只是不公平。createObjectUrl 在内存中创建对您上传的文件的引用。

ReadAsDataUrl 读取文件,以 base64 编码,创建一个字符串对象,然后浏览器必须再次读取该字符串,从 base64 解码。

不同之处还在于 fabricJS 使用 drawImage 和 9 个参数绘制图像,而您使用的是 3 个参数版本。

// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e) {
var t0 = performance.now();

var promise = new Promise(function(resolve) {
var URL = window.webkitURL || window.URL;
var ctx = document.getElementById('canvas').getContext('2d');
canvas = document.getElementById('canvas');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
console.log('Standard Import')
console.log('Start Time: ', Math.round(t0/1000))
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
resolve("done")
};
img.src = url;
});

promise.then(function(result) {
var t1 = performance.now()
console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
var dataURL = canvas.toDataURL('image/png')
return
}).then(function(result){
t2 = performance.now()
console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
return
});
}

// Fabric Import
function handleFilesFabric(e) {
var t0 = performance.now();
var canvas = new fabric.StaticCanvas('canvas2', {enableRetinaScaling: false, renderOnAddRemove: false });
var promise = new Promise(function(resolve) {

var reader = new FileReader();
var URL = window.webkitURL || window.URL;
var url = URL.createObjectURL(e.target.files[0]);
var imgObj = new Image();

imgObj.onload = function () {
console.log('Fabric Import')
console.log('Start Time: ', Math.round(t0/1000))

var image = new fabric.Image(imgObj);
canvas.setDimensions({ width: imgObj.width, height: imgObj.height});
canvas.add(image);
resolve("done")
}
imgObj.src = url;
});

promise.then(function(result) {
var t1 = performance.now()
console.log('Done img.onload() Elapsed Time: ', Math.round(t1 - t0)/1000);
canvas.renderAll();
var dataURL = canvas.lowerCanvasEl.toDataURL('image/png')
return
}).then(function(result){
t2 = performance.now()
console.log('Done canvas.ToDataURL() Elapsed Time: ', Math.round(t2 - t0)/1000)
return
});
}

window.onload = function() {
// Standard Import
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
input.addEventListener('change', handleFilesFabric, false);
};
canvas {
border: 2px solid;
}
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Upload & Display Image w/ Canvas</title>
<link rel="stylesheet" href="css/style.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.3/fabric.min.js"></script>
</head>
<body>
<h1> Upload & Display Image</h1>
<canvas width="400" height="400" id="canvas"></canvas>
<canvas width="400" height="400" id="canvas2"></canvas>
<br>
<b>Standard Add Image</b><br>
<input type="file" id="input"/>
<br>
</body>
</html>

关于javascript - Fabric JS : Performance of very large images (20mb+),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53267113/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com