Javascript Typed Arrays and Endianness

I use WebGL to render a binary encoded grid file. The binary file is written in big-endian format (I can check this by opening the file in a hex editor or viewing network traffic using a violinist). When I try to read a binary answer using Float32Array or Int32Array, the binary is interpreted as little-endian and my values ​​are incorrect:

// Interpret first 32bits in buffer as an int var wrongValue = new Int32Array(binaryArrayBuffer)[0]; 

I cannot find references to the standard specification of typed arrays at http://www.khronos.org/registry/typedarray/specs/latest/ , so I wonder what kind of deal this is? Should I assume that all binary data should be insignificant when reading using typed arrays?

To work around the problem, I can use the DataView object (discussed in the previous link) and call:

 // Interpret first 32bits in buffer as an int var correctValue = new DataView(binaryArrayBuffer).getInt32(0); 

DataView functions, such as "getInt32", by default read the default values.

(Note: I tested Google Chrome 15 and Firefox 8, and they both behave the same)

+42
javascript endianness webgl arraybuffer typed-arrays
Oct 23 2018-11-23T00:
source share
4 answers

Unfortunately, the current behavior is that continentality refers to basic equipment. Since almost all desktop computers are x86, this means that it is little-endian. Most ARM operating systems use little-endian mode (ARM processes are bi-directional and can work in both).

The reason this is somewhat sad is that almost no one will check if their code works on a large number of hardware, damaging what it does, and the fact that the entire web platform was developed around code that works evenly across all implementations and platforms that it violates.

+46
Oct 23 2018-11-23T00:
source share

Taken from here http://www.khronos.org/registry/typedarray/specs/latest/ (when this specification is fully implemented) you can use:

 new DataView(binaryArrayBuffer).getInt32(0, true) // For little endian new DataView(binaryArrayBuffer).getInt32(0, false) // For big endian 

However, if you cannot use this method because they are not implemented, you can always check the value of the magic file (almost every format has a magic value) in the header to see if it needs to be inverted according to your endian.

In addition, you can save Endiannes-dependent files to your server and use them accordingly as detected by end-users.

+20
Oct 24 '11 at 13:22
source share

FYI, you can use the following javascript function to determine the limb of the machine, after which you can transfer the file with the appropriately formatted client (you can save two versions of the file on the server, a large end and a small end):

 function checkEndian() { var arrayBuffer = new ArrayBuffer(2); var uint8Array = new Uint8Array(arrayBuffer); var uint16array = new Uint16Array(arrayBuffer); uint8Array[0] = 0xAA; // set first byte uint8Array[1] = 0xBB; // set second byte if(uint16array[0] === 0xBBAA) return "little endian"; if(uint16array[0] === 0xAABB) return "big endian"; else throw new Error("Something crazy just happened"); } 

In your case, you will probably have to either recreate the file at the small end, or skip the entire data structure to make it insignificant. Using a twist of the above method, you can change it on the fly (not really recommended and only make sense if the whole structure has the same tightly packed types, in fact you can create a stub function that changes the bytes as needed):

 function swapBytes(buf, size) { var bytes = new Uint8Array(buf); var len = bytes.length; var holder; if (size == 'WORD') { // 16 bit for (var i = 0; i<len; i+=2) { holder = bytes[i]; bytes[i] = bytes[i+1]; bytes[i+1] = holder; } } else if (size == 'DWORD') { // 32 bit for (var i = 0; i<len; i+=4) { holder = bytes[i]; bytes[i] = bytes[i+3]; bytes[i+3] = holder; holder = bytes[i+1]; bytes[i+1] = bytes[i+2]; bytes[i+2] = holder; } } } 
+20
Oct 26 '13 at 11:14
source share

Other answers seem obsolete to me, so here is a link to the latest specification:

http://www.khronos.org/registry/typedarray/specs/latest/#2.1

In particular:

Types of typed array types work with host computer content.

The DataView type works with data with the specified content (big-endian or little-endian).

So, if you want to read / write data in Big Endian (Network Byte Order), see http://www.khronos.org/registry/typedarray/specs/latest/#DATAVIEW

 // For multi-byte values, the optional littleEndian argument // indicates whether a big-endian or little-endian value should be // read. If false or undefined, a big-endian value is read. 
+11
Jul 03 '14 at 12:05
source share



All Articles