3

I have the following case. I capture a webcam frame via a canvas with context.getImageData().data. That gives me a nice Array (or UInt8ClampedArray says Bidelman) of ints like [r, g, b, a, r, g, b, a, r, g, b, a, etc.] when I console.log() them. Now I want to send this to a node.js server via binaryjs and of course the data get's scrambled like hell: https://gist.github.com/thgie/6550638

How can I convert the Array to something binary first or how do I get the binary back to a readable array?

Code examples

Client:

client.send(ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT).data, {'id': 'bin', 'frame': frame});

Server:

client.on('stream', function(stream, meta){

  var bufs = [];

  stream.on('data', function(data){
    bufs.push(data);
  });

  stream.on('end', function(){

    var buf = Buffer.concat(bufs);

    fs.writeFile(__dirname + "/tmp/"+meta.frame+".dat", buf, "binary", function(err) {
      if(err) {
        console.log(err);
      } else {
        console.log("The file was saved!");
      }
    });
  });
}

It will look like this:

H>DÿNDJÿL@FÿPCJÿR@KÿQ?IÿLDPÿKCOÿMCKÿLAIÿL@DÿL@DÿLBGÿKAFÿIAHÿLDLÿLAIÿLAIÿO@IÿO@IÿIAJÿJBKÿMCIÿNDJÿQEIÿQEIÿPGHÿOFGÿMIHÿMIHÿPDFÿNCEÿIBDÿLEHÿPDFÿPDFÿMHLÿLGKÿMHLÿNIMÿOGLÿNFKÿOEMÿPFNÿRFSÿPERÿPERÿPERÿRGOÿSHPÿSGMÿSGMÿRJRÿQIPÿQJNÿRKPÿRKPÿQJNÿSGMÿSGMÿOHJÿSLOÿQJLÿRKMÿSIJÿTKKÿQLPÿPJNÿSLQÿRKPÿSLQÿUMRÿSKSÿUMTÿVMWÿSKUÿUJUÿRGQÿUMTÿUMTÿSKUÿVMWÿSMTÿSMTÿQNVÿQNVÿSMVÿTNWÿZMVÿXKTÿUJUÿVKVÿTOSÿTOSÿWQUÿWQUÿYTVÿYTVÿXRVÿUPTÿYSZÿYSZÿXRVÿZUYÿWPRÿYRTÿWRQÿXSRÿVOOÿWPPÿXRVÿXRVÿZOYÿ[P[ÿZO[ÿ\Q^ÿZT_ÿZT_ÿZV`ÿZV`ÿ]T^ÿ]T^ÿ^TZÿ`V[ÿ[VXÿ[VXÿ]UZÿ^V[ÿZV`ÿ[Waÿ_Xdÿ_Xdÿ]X`ÿ]X`ÿaZ_ÿaZ_ÿ_Y]ÿ`[_ÿ`Y]
4
  • If you are using binaryjs then it does it for you. Make sure you use binaryjs on server and client sides to communicate, and it will handle compressing and decompressing for you. Commented Sep 13, 2013 at 14:41
  • Then I do something wrong with the buffer. Because doesn't matter how I convert it, I just get scrambled traces. Commented Sep 14, 2013 at 15:19
  • The buf argument you're passing to fs.writeFile is an actual Buffer, right? Something is stringifying your data, apparently. Commented Sep 14, 2013 at 17:05
  • I'm very sure it's a buffer. From the docs of binaryjs: On Node.js, binary data is received as Buffer. But I don't send binary data. I send an array and I'm somehow not convinced binaryjs solves that for me. Maybe if I send an ArrayBuffer. Commented Sep 15, 2013 at 19:58

1 Answer 1

1

As far as the browser side, you can verify easily enough using chrome's dev tools. Look at the binary traffic and it will tell you if your sending binary of text frames. They are different kinds of frames in the websocket spec.

On the node side, you can verify your buffer values are truly node buffers by using Buffer.isBuffer(). I see you're writing your buffer using the "binary" string encoding. This is probably not what you want. In node, the encoding for native Buffer instances is null. The "binary", "ascii", "utf8", "hex", "base64" encodings are all string encodings/decodings. What the binary encoding means is that every byte is stored in the string as a 8-bit unicode code point.

// Convert a binary buffer into a "binary" encoded string.
function binaryEncode(buffer) {
  var string = "";
  for (var i = 0, l = buffer.length; i < l; i++) {
    string += String.fromCharCode(buffer[i]);
  }
  return string
}

// Convert a "binary" encoded string into a binary buffer.
function binaryDecode(string) {
  var length = string.length;
  var buffer = new Buffer(length);
  for (var i = 0; i < length; i++) {
    buffer[i] = string.charCodeAt(i);
  }
} 

Storing binary data can thus be done quite safely in JavaScript strings (which are defined as having 16 bit unicode code points per character). It's not the most efficient thing since you're wasting the upper 8 bits of every character and this is why node.js prefers native Buffers. But in things like browser crypto libraries, this "binary" string encoding is common since it is supported on all JS platforms.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.