So I have a file which contains values of 12 bit unsigned integers. I have no problem reading the file directly into a UInt8Array or UInt16Array but the values are of course incorrect and the length of those arrays is incorrect. How can I read those 12 bit values and save them into a Uint16Array but the values must be correct?
So I read that I could read the values as 3 8bit integers and then split the midle one into two parts but I dont know how to really do this in JavaScript.
The code bellow makes the correct length of UInt16Array, so the splitting is right, but the values in array are not correct:
fileReader.onload = () => {
const arrayBuffer = fileReader.result;
const dataView = new DataView(arrayBuffer);
const length = Math.floor((dataView.byteLength * 8) / 12);
const result = new Uint16Array(length);
let byteOffset = 0;
let bitOffset = 0;
let currentIndex = 0;
for (let i = 0; i < length; i++) {
const bitsRemaining = 12 - bitOffset;
const bitsToRead = Math.min(bitsRemaining, 16);
let value = (dataView.getUint8(byteOffset) << 8) | dataView.getUint8(byteOffset + 1);
value >>= (16 - bitOffset - bitsToRead);
value &= (0b1 << bitsToRead) - 1;
result[currentIndex] = value;
bitOffset += bitsToRead;
if (bitOffset === 12) {
byteOffset += 1;
bitOffset = 0;
}
currentIndex++;
}
}
2
Answers
So i managed to get the result I wanted with the code below:
With consideration of nibble order (something similar to endianness for bytes), 4 most expected layouts can be implemented within a single generic function:
The function loops through 3-byte chunks to run faster.
However if nibbles are mixed in a more complicated way, it would be better to write some dedicated method for extraction.