Mobile Web Wearable Web

Typed Array - Khronos: Handling Binary Data

This tutorial demonstrates how you can access binary data in JavaScript.

Warm-up

Become familiar with the Typed Array - Khronos API basics by learning about:

Creating an Array Buffer

To handle binary data in your application with JavaScript, you must learn to create array buffers:

  1. Create a new ArrayBuffer with a specific length:
    <script>
       var log = document.getElementById("log");
    
       /* Create a 12-byte buffer */
       var buffer = new ArrayBuffer(12);
       var x = new Int32Array(buffer);
    
       /* Check the buffer length */
       log.innerHTML = "<div>" + buffer.byteLength + "<div>";

    The content of the array buffer is initialized to 0. If the requested number of bytes are not allocated, an exception is raised.

  2. Slice the array buffer to copy the buffer bytes and return a new array buffer:
       /* Get slice: "1234"*/    
       x[1] = 1234;
       var slice = buffer.slice(4);
       var y = new Int32Array(slice);
       log.innerHTML += "<div>" + x[1] + "<div>";
       log.innerHTML += "<div>" + y[0] + "<div>";
    
       /* Get slice: "6789"*/
       x[1] = 6789;
       log.innerHTML += "<div>" + x[1] + "<div>";
       log.innerHTML += "<div>" + y[0] + "<div>";
    </script>

Figure: Creating and slicing array buffers (in mobile applications only)

Creating and slicing array buffers (in mobile applications only)

Source Code

For the complete source code related to this use case, see the following file:

Creating Typed Array Views

To handle binary data in your application with JavaScript, you must learn to access the binary data for reading and writing:

  1. Create new instances of the typed array view types with a general fixed-length binary buffer:
    <script>
       /* 8-bit 2's complement signed integer */
       var int8 = new Int8Array(8);
       /* 8-bit unsigned integer */
       var uint8 = new Uint8Array(16);
       /* 8-bit unsigned integer (clamped) */
       var uint8Cl = new Uint8ClampedArray(32);
       /* 16-bit 2's complement signed integer */
       var int16 = new Int16Array(64);
       /* 16-bit unsigned integer */
       var uint16 = new Uint16Array(8);
       /* 32-bit 2's complement signed integer */
       var int32 = new Int32Array(16);
       /* 32-bit unsigned integer */
       var uint32 = new Uint32Array(32);
       /* 32-bit IEEE floating point */
       var float32 = new Float32Array(64);
       /* 64-bit IEEE floating point */
       var float64 = new Float64Array(8);
    </script>
    
    Note
    In the above code, to access a buffer with an array of 16-bit signed integers, use the Int16Array instance that references an array buffer.
  2. Create a typed array view:
    <script>
       var log = document.getElementById("log");
       /* Create an array buffer */
       var buffer = new ArrayBuffer(12);
    	        
       /* Create a typed array view that points to the array buffer */
       var x = new Int32Array(buffer, 0, 2);
    

    You can use the view to establish a detailed data structure by creating the value of 32-bit signed integers in a byte-type composition element.

  3. Use the typed array view buffer:
       var y = new Int32Array(x.buffer, 4, 2);
       log.innerHTML += "<div>" + (x.buffer === y.buffer) + "<div>";
    	        
       /* Use the byteLength, length, and byteOffset properties */
       log.innerHTML += "<div>" + x.byteLength + "<div>";
       log.innerHTML += "<div>" + (x.length * Int32Array.BYTES_PER_ELEMENT) + "<div>";
       log.innerHTML += "<div>" + x.byteOffset + "<div>"; 
    </script>

    Typed Array implementation

  4. Replace the CanvasPixelArray instance with the Uint8ClampedArray instance:
    <script>
       var buffer = new ArrayBuffer(12);
       var x = new Uint8ClampedArray(buffer, 4, 2);
       log.innerHTML += "<div>[Result1]</div>";
       log.innerHTML += "<div>" + x.byteLength + "<div>";
       log.innerHTML += "<div>" + x.length + "<div>";
       log.innerHTML += "<div>" + Uint8ClampedArray.BYTES_PER_ELEMENT + "<div>";
    
       var x = new Uint8ClampedArray(10);
       x.set([18, 93, 42], 3);
       log.innerHTML += "<br><div>[Result2]</div>";
       log.innerHTML += "<div>" + x[3] + "<div>";
       log.innerHTML += "<div>" + x[4] + "<div>";
       log.innerHTML += "<div>" + x[5] + "<div>";
    
       var x = new Uint8ClampedArray([0, 1, 2, 3, 4, 5]);
       var y = x.subarray(2, 5);
       log.innerHTML += "<br><div>[Result3]</div>";
       log.innerHTML += "<div>" + y.length + "<div>";	
    </script>

    The Uint8ClampedArray behavior is identical to the other typed array views. The only notable exception is that the setters and constructors use clamping rather than modulo arithmetic while converting incoming number values.

    Clamped Array implementation

  5. When an ArrayBuffer with heterogeneous type of data is used, you can take advantage of the DataView of the buffer:
    <script>
       var log = document.getElementById("log");
        
       /* Create DataView */
       var x = new DataView(new ArrayBuffer(12), 0);
    
       /* Store the variable */
        x.setFloat32(1, Math.PI);
    
       /* Get the variable */
       log.innerHTML += "<div>" + x.getFloat32(1) + "<div>";
       log.innerHTML += "<div>" + Math.PI + "<div>"; 
    </script>

    The DataView stores the values of the given type at the specified byte offset from the start of the view. Moreover, alignment is not a constraint, and it can store the multi-byte values at any offset. For multi-byte values, the optional littleEndian argument indicates that the value can be stored in a big-endian or little-endian byte order. If the argument is set to false or is undefined, the value gets stored in the big-endian byte order.

    DataView

Source Code

For the complete source code related to this use case, see the following files:

Using Typed Arrays

To handle binary data in your application with JavaScript, you must learn to deliver binary data effectively in other HTML5 APIs that employ a typed array:

  1. For the WebGL - Khronos API (in mobile or wearable applications), import the gl.bufferData() method to set the buffer object to deliver texture data:
    <script>
       var textureCoords = [0.0,  0.5, 0.25, 0.5, 0.25, 1.0, 0.0,  1.0,  /* Front */
                            0.5,  0.5, 0.75, 0.5, 0.75, 1.0, 0.5,  1.0,  /* Back */
                            0.0,  0.5, 0.25, 0.5, 0.25, 0.0, 0.0,  0.0,  /* Top */
                            0.25, 0.5, 0.5,  0.5, 0.5,  0.0, 0.25, 0.0,  /* Bottom */
                            0.25, 0.5, 0.5,  0.5, 0.5,  1.0, 0.25, 1.0,  /* Right */
                            0.75, 0.5, 1.0,  0.5, 1.0,  1.0, 0.75, 1.0]; /* Left */
    
       cubeVertexTextureCoordBuffer = gl.createBuffer();
       gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
       gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
       cubeVertexTextureCoordBuffer.itemSize = 2;
       cubeVertexTextureCoordBuffer.numItems = 24;
    </script>
  2. For the HTML5 canvas element API (in mobile or wearable applications), use the typed array with the following steps:
    1. Create an ImageData object of the canvas internally.
    2. Deliver the pixel expression of the canvas element:
      <script>
         var tempContext = canvas.getContext("2d");
         tempContext.drawImage(picture, 0, 0, canvas.width, canvas.height);
         var pixels = canvas.width * canvas.height * 4;
         var canvasData = tempContext.getImageData(0, 0, canvas.width, canvas.height);
         var binaryData = canvasData.data;
      </script>
    Note
    The pixel array of canvas can be created and edited without direct manipulation of the canvas element.
  3. For the XMLHttpRequest Level 1 API or XMLHttpRequest Level 2 API, set the response type of the XMLHttpRequest object as arraybuffer to receive a typed array response. This way by delivering data directly in multimedia, you can parse the binary file through the network:
    this.setSound = function() 
    {
       var request = new XMLHttpRequest();
       request.open("GET", url, true);
       request.responseType = "arraybuffer";
    
       request.onload = function() 
       {
          var data = request.response;
       };
       request.send();
    }
Go to top