Fabric JS: Performance of very large images (20mb+)
I'm using Fabric JS to manipulate very large images (20mb+). I have found that Fabric is considerably slower at handling large images in a canvas as compared to using the standard Canvas API.
The below code snippet has two input buttons, one for adding an image to canvas using standard Canvas API and the other using Fabric JS. Each method will also convert the canvas to a data url using toDataUrl()
. Each method also logs three times: start time, time when img.onload function completes, and when toDataUrl()
completes.
Here is a table comparing import+export times that I tested for varying image sizes:
import times for 500kb to 50mb photos
Here is a graph displaying the performance of Fabric import+export times vs Canvas API: graph
Questions:
- Why is Fabric performance so much slower than Canvas API at importing+exporting large images on a canvas?
- Is there a way to increase Fabric performance when using large images?
- Are my test cases accurately representing Fabric performance?
// 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) );
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>
javascript canvas fabricjs
add a comment |
I'm using Fabric JS to manipulate very large images (20mb+). I have found that Fabric is considerably slower at handling large images in a canvas as compared to using the standard Canvas API.
The below code snippet has two input buttons, one for adding an image to canvas using standard Canvas API and the other using Fabric JS. Each method will also convert the canvas to a data url using toDataUrl()
. Each method also logs three times: start time, time when img.onload function completes, and when toDataUrl()
completes.
Here is a table comparing import+export times that I tested for varying image sizes:
import times for 500kb to 50mb photos
Here is a graph displaying the performance of Fabric import+export times vs Canvas API: graph
Questions:
- Why is Fabric performance so much slower than Canvas API at importing+exporting large images on a canvas?
- Is there a way to increase Fabric performance when using large images?
- Are my test cases accurately representing Fabric performance?
// 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) );
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>
javascript canvas fabricjs
add a comment |
I'm using Fabric JS to manipulate very large images (20mb+). I have found that Fabric is considerably slower at handling large images in a canvas as compared to using the standard Canvas API.
The below code snippet has two input buttons, one for adding an image to canvas using standard Canvas API and the other using Fabric JS. Each method will also convert the canvas to a data url using toDataUrl()
. Each method also logs three times: start time, time when img.onload function completes, and when toDataUrl()
completes.
Here is a table comparing import+export times that I tested for varying image sizes:
import times for 500kb to 50mb photos
Here is a graph displaying the performance of Fabric import+export times vs Canvas API: graph
Questions:
- Why is Fabric performance so much slower than Canvas API at importing+exporting large images on a canvas?
- Is there a way to increase Fabric performance when using large images?
- Are my test cases accurately representing Fabric performance?
// 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) );
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>
javascript canvas fabricjs
I'm using Fabric JS to manipulate very large images (20mb+). I have found that Fabric is considerably slower at handling large images in a canvas as compared to using the standard Canvas API.
The below code snippet has two input buttons, one for adding an image to canvas using standard Canvas API and the other using Fabric JS. Each method will also convert the canvas to a data url using toDataUrl()
. Each method also logs three times: start time, time when img.onload function completes, and when toDataUrl()
completes.
Here is a table comparing import+export times that I tested for varying image sizes:
import times for 500kb to 50mb photos
Here is a graph displaying the performance of Fabric import+export times vs Canvas API: graph
Questions:
- Why is Fabric performance so much slower than Canvas API at importing+exporting large images on a canvas?
- Is there a way to increase Fabric performance when using large images?
- Are my test cases accurately representing Fabric performance?
// 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) );
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>
// 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) );
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>
// 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) );
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>
javascript canvas fabricjs
javascript canvas fabricjs
asked Nov 12 '18 at 17:21
user1710344user1710344
1112
1112
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
I refactored the code a bit to be more fair:
Same way of loading the image and both event run after the other on 2 different canvases.
Also remove additional fabricJS functionality that for this test do not make sense. I think that for bigger image the differnce should be lower now, can you try in the snippet with a big image?
By the way you cannot compare a URL.createObjectUrl from a file with a file reader on a dataUrl. Is just unfair.
createObjectUrl create a reference in memory to the file you uploaded.
ReadAsDataUrl read the file, encode in base64, create a string object, then the browser has to read that string again, decode from base64.
The difference could also be in the fact fabricJS paint the image with drawImage and 9 args, while you used the 3 args version.
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53267113%2ffabric-js-performance-of-very-large-images-20mb%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I refactored the code a bit to be more fair:
Same way of loading the image and both event run after the other on 2 different canvases.
Also remove additional fabricJS functionality that for this test do not make sense. I think that for bigger image the differnce should be lower now, can you try in the snippet with a big image?
By the way you cannot compare a URL.createObjectUrl from a file with a file reader on a dataUrl. Is just unfair.
createObjectUrl create a reference in memory to the file you uploaded.
ReadAsDataUrl read the file, encode in base64, create a string object, then the browser has to read that string again, decode from base64.
The difference could also be in the fact fabricJS paint the image with drawImage and 9 args, while you used the 3 args version.
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
add a comment |
I refactored the code a bit to be more fair:
Same way of loading the image and both event run after the other on 2 different canvases.
Also remove additional fabricJS functionality that for this test do not make sense. I think that for bigger image the differnce should be lower now, can you try in the snippet with a big image?
By the way you cannot compare a URL.createObjectUrl from a file with a file reader on a dataUrl. Is just unfair.
createObjectUrl create a reference in memory to the file you uploaded.
ReadAsDataUrl read the file, encode in base64, create a string object, then the browser has to read that string again, decode from base64.
The difference could also be in the fact fabricJS paint the image with drawImage and 9 args, while you used the 3 args version.
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
add a comment |
I refactored the code a bit to be more fair:
Same way of loading the image and both event run after the other on 2 different canvases.
Also remove additional fabricJS functionality that for this test do not make sense. I think that for bigger image the differnce should be lower now, can you try in the snippet with a big image?
By the way you cannot compare a URL.createObjectUrl from a file with a file reader on a dataUrl. Is just unfair.
createObjectUrl create a reference in memory to the file you uploaded.
ReadAsDataUrl read the file, encode in base64, create a string object, then the browser has to read that string again, decode from base64.
The difference could also be in the fact fabricJS paint the image with drawImage and 9 args, while you used the 3 args version.
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
I refactored the code a bit to be more fair:
Same way of loading the image and both event run after the other on 2 different canvases.
Also remove additional fabricJS functionality that for this test do not make sense. I think that for bigger image the differnce should be lower now, can you try in the snippet with a big image?
By the way you cannot compare a URL.createObjectUrl from a file with a file reader on a dataUrl. Is just unfair.
createObjectUrl create a reference in memory to the file you uploaded.
ReadAsDataUrl read the file, encode in base64, create a string object, then the browser has to read that string again, decode from base64.
The difference could also be in the fact fabricJS paint the image with drawImage and 9 args, while you used the 3 args version.
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
// Standard Import
fabric.Object.prototype.objectCaching = false;
function handleFiles(e)
var t0 = performance.now();
var promise = new Promise(function(resolve)
var URL = window.webkitURL );
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) );
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>
edited Nov 14 '18 at 12:40
answered Nov 14 '18 at 12:29
AndreaBogazziAndreaBogazzi
9,89532248
9,89532248
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53267113%2ffabric-js-performance-of-very-large-images-20mb%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown