1

Assuming I get binary image data from somewhere (web sockets in my case), what's the fastest way to render them in a web browser?

I came up with this approach using Canvas and Blobs.

    var context = canvas.getContext('2d')
    var img = new Image()

    img.onload = function() {
      context.drawImage(img, 0, 0)
      window.URL.revokeObjectURL(this.src)
    }

    img.src = window.URL.createObjectURL(new Blob([data], {'type': 'image\/jpeg'}))

It's already pretty fast (~3ms - 10ms rendering time vor a full HD jpeg). Is there another (faster) way, maybe without the Image element?

edit: yes, this is mad science, but in order to achieve 60fps every ms counts.

klaemo
  • 169
  • 6
  • 3
    What on earth are you doing that 10ms is not fast enough? – JJJ May 13 '15 at 16:23
  • How do you know that it takes that time? – gab06 May 13 '15 at 16:24
  • So, faster in this case would be a millisecond or less... ?? Really? Think about it! – LcSalazar May 13 '15 at 16:27
  • Couldn't you just use the base64 string like [this](http://stackoverflow.com/questions/1207190/embedding-base64-images)? – Seiyria May 13 '15 at 16:29
  • using img src-data is pretty fast something like [this](http://stackoverflow.com/questions/2329364/how-to-embed-images-in-a-single-html-php-file) – Blauharley May 13 '15 at 16:33
  • @Juhana given you only have 16 ms to render a frame to get a no-jank 60 fps experience, 10 ms is a large chunk of your frame budget. – Domenic May 13 '15 at 16:34
  • Why do you want to get the ms down? Are you trying to see how low you can go or are you noticing performance issues? – wolfhammer May 13 '15 at 17:13
  • Somewhere on SO it says "keep an open mind"... I'm just exploring things. Trying to get to 60fps every ms counts. – klaemo May 13 '15 at 17:44
  • @Juhana It's an experiment where a server spits out jpegs at about 60fps. I want to render them as fast as possible. – klaemo May 13 '15 at 17:50
  • @Seiyria base64 is pretty slow. – klaemo May 13 '15 at 17:50

1 Answers1

0

You could try requestAnimationFrame. Here's a shim from Paul Irish.

// shim layer with setTimeout fallback
window.requestAnimationFrame = (function(){
  return  window.requestAnimationFrame       ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame    ||
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

// ...

img.onload = function() {
    var self = this;
    requestAnimationFrame(function(){
        context.drawImage(self, 0, 0)
        window.URL.revokeObjectURL(self.src)
    });
};
wolfhammer
  • 2,501
  • 1
  • 10
  • 11
  • WTH would deferring the call be any faster than calling `drawImage` immediately? – Bergi May 13 '15 at 16:52
  • This will speed things up for multiple images. Combining rendering into one repaint will make things run smoother for something like a gallery. For a one image page it won't help much. @Bergi – wolfhammer May 13 '15 at 17:02
  • Ah, I see. But if you call `requestAnimationFrame` multiple times within a frame (for multiple images), then that `setTimeout` shim does not work. – Bergi May 13 '15 at 17:06
  • …and you need something more advanced like `(function(cbs){function frame(){while(cbs.length)cbs.shift()();cbs=null}return function raf(cb){if(!cbs){setTimeout(frame,100/6);cbs=[];}cbs.push(cb)}}(null))` – Bergi May 13 '15 at 17:12
  • That's a nice one. Would be interesting to see if it can achieve higher frame rate on some browsers. Maybe 1000/120. That would be 8ms. @Bergi – wolfhammer May 13 '15 at 17:25
  • I've actually done that. It won't speed up things (I think), but should keep the frame rate more stable. – klaemo May 13 '15 at 17:46