Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which ArrayBufferView

I'm retrieving an ArrayBuffer over XHR and want to save it to the FileSystem API using a FileWriter. The FileWriter expects a Blob and the Blob constructor won't take an ArrayBuffer, it takes an ArrayBufferView.

There are many ArrayBufferViews to choose from, how do I know which is the correct to use?

like image 966
Matthew Avatar asked Jan 13 '13 22:01

Matthew


1 Answers

At MDN, you can find an overview of all available ArrayBufferView subclasses:

Type         | Size | Description                           | Equivalent C type
-------------+------+---------------------------------------+------------------
Int8Array    | 1    | 8-bit twos complement signed integer  | signed char
Uint8Array   | 1    | 8-bit unsigned integer                | unsigned char
Int16Array   | 2    | 16-bit twos complement signed integer | short
Uint16Array  | 2    | 16-bit unsigned integer               | unsigned short
Int32Array   | 4    | 32-bit twos complement signed integer | int
Uint32Array  | 4    | 32-bit unsigned integer               | unsigned int
Float32Array | 4    | 32-bit IEEE floating point number     | float
Float64Array | 8    | 64-bit IEEE floating point number     | double

Basically, this lists what memory spaces each item of the array would occupy and if it's a plain number or a FP number. I'm not sure what languages you're familiar with, but if it also covers Java, then it is basically the same choice as you'd make on byte[], short[], int[], float[] and double[] (Java is always signed, so that part doesn't matter).

We know, binary data like images is usually represented as a byte array. A short/int/long array can also, but this is a waste of memory space. If you would store a 100KB image (note that "B" stands for byte, which is 8 bits) in an int array instead of a byte array, then it would occupy 400KB of memory, which is a waste of 300KB. So the smallest one, Int8Array, would already suffice with regard to memory space. If you'd ever like to programmatically traverse it — which is very unlikely in this case — as an unsigned array, then you may opt for the Uint8Array instead where each item holds values 0 to 255 instead of values -128 to 127.

Here's a copy'n'paste'n'runnable kickoff example which downloads an image file from the server, saves it to the temporary local storage space and presents it as an <img> in the body (little jQuery is required for that part). This example assumes that the image.png file is located in the same base folder as the JS (or HTML, in case JS is inlined) file is been downloaded from:

window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024*1024, startDownload, errorHandler);

var errorHandler = function(error) {
    console.log('FS error: ' + error);
}

var xhr = new XMLHttpRequest();
xhr.open('GET', 'image.png', true);
xhr.responseType = 'arraybuffer';

function startDownload(fileSystem) {
    xhr.onload = function(event) {
        var content = new Int8Array(this.response);
        fileSystem.root.getFile('/image.png', { 'create': true }, function(fileEntry) {
            fileEntry.createWriter(function(fileWriter) {
                fileWriter.onwriteend = function(event) {
                    $('body').append('<p>Image successfully downloaded:</p>')
                             .append('<p><img src="' + fileEntry.toURL() + '"/></p>');
                };

                var blob = new Blob([content], { type: 'image/png' });
                fileWriter.write(blob);
            }, errorHandler);
        });
    }

    xhr.send();
}

Note, as of the current state, this works in Chrome only.

like image 172
BalusC Avatar answered Oct 20 '22 19:10

BalusC