Gb01
Gb01

Reputation: 1243

HTML5 load a png buffer into a canvas (for streaming purpose)

Through a websocket, I retrieve a binary buffer of an image in a PNG format (something like that).

I want to load this PNG buffer into a canvas, and then read the different pixels to read the uncompressed data.

I managed to do it but it is stupid:

function onBinaryMessage(/*ArrayBuffer*/ input) {
  input = new Uint8Array(input);

  var str = '';
  for (var i = 0; i < input.byteLength; i++)
    str = str + String.fromCharCode(input[i]);

  var image = document.getElementById("image");
  image.src = 'data:image/png;base64,' + btoa(str);

  var c = document.getElementById("canvas");
  var ctx = c.getContext("2d");
  ctx.drawImage(image, 0, 0);
  var imgData = ctx.getImageData(0, 0, image.width, image.height);
  console.log(imgData);
}

I have to convert my binary into a string to encode64 this string, and than I affect my image src to this newly created encoded64 string... The browser have to re-convert this encoded64 data into the original PNG buffer I got...

Is there any way to directement set the canvas buffer? Or is there any method to better handle streaming?

I think I could use the File API to write the buffer into a temporary file but it would cost a lot to create a file :(

Any suggestion?

Upvotes: 9

Views: 13275

Answers (1)

user1693593
user1693593

Reputation:

You can convert your input buffer to a Blob instead, obtain an URL for it and use that to draw onto the canvas instead:

function onBinaryMessage(input) {

    var blob = new Blob([input], {type: 'image/png'});
    var url = URL.createObjectURL(blob);
    var img = new Image;

    img.onload = function() {
        var ctx = document.getElementById("canvas").getContext('2d');
        ctx.drawImage(this, 0, 0);
        URL.revokeObjectURL(url);
    }
    img.src = url;
}

Just note that this will be asynchronous and you would need to provide a callback-mechanism inside the onload handler (in any case you really need to do that in your own example as well). But you won't have to convert to base64 etc. which is a relative costly operation.

Also note that URL.createObjectURL is currently experimental.

Upvotes: 12

Related Questions