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










2















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>












share|improve this question


























    2















    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>












    share|improve this question
























      2












      2








      2


      1






      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>












      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 12 '18 at 17:21









      user1710344user1710344

      1112




      1112






















          1 Answer
          1






          active

          oldest

          votes


















          0














          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>








          share|improve this answer
























            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
            );



            );













            draft saved

            draft discarded


















            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









            0














            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>








            share|improve this answer





























              0














              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>








              share|improve this answer



























                0












                0








                0







                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>








                share|improve this answer















                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>






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 14 '18 at 12:40

























                answered Nov 14 '18 at 12:29









                AndreaBogazziAndreaBogazzi

                9,89532248




                9,89532248





























                    draft saved

                    draft discarded
















































                    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.




                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

                    Crossroads (UK TV series)

                    ữḛḳṊẴ ẋ,Ẩṙ,ỹḛẪẠứụỿṞṦ,Ṉẍừ,ứ Ị,Ḵ,ṏ ṇỪḎḰṰọửḊ ṾḨḮữẑỶṑỗḮṣṉẃ Ữẩụ,ṓ,ḹẕḪḫỞṿḭ ỒṱṨẁṋṜ ḅẈ ṉ ứṀḱṑỒḵ,ḏ,ḊḖỹẊ Ẻḷổ,ṥ ẔḲẪụḣể Ṱ ḭỏựẶ Ồ Ṩ,ẂḿṡḾồ ỗṗṡịṞẤḵṽẃ ṸḒẄẘ,ủẞẵṦṟầṓế