2

I've been trying a few different solutions to Base64 encode and decode a javascript Float32Array so I can send it to my Web API in a JSON doc. But every time I decode the string back to an array of float, I get a longer one than I started with. I've tried the following approaches

They all "work" in that they encode my Float32Array which has a length of 76800 to a BASE64 string. But whenever I decode that string, I get a longer array. Even when I use their own "decode" functions.

For example here is me testing the first approach, but I see this with all of them. ('pcdRef.current' is my Float32Array). This code...

var base64String = encode(new Uint8Array(pcdRef.current.buffer));            
var prev = decode(base64String)
var prevArray = new Float32Array(prev.buffer);

console.log("original length = " + pcdRef.current.length + ", rehydrated length = " + prevArray.length);

...gives me this console output

original length = 76800, rehydrated length = 77284

The same is true of the data that my actual Web API receives.

Can someone tell me what I am doing wrong?

Joe
  • 5,394
  • 3
  • 23
  • 54

1 Answers1

1

Double-check the properties of the Float32Array's underlying buffer. A TypedArray (such as Float32Array) may be created as a view of an underlying buffer, at an arbitrary offset and with an arbitrary length. This means that accessing an array's buffer without also processing byteOffset and byteLength may fail.

Demonstration:

const buffer = new ArrayBuffer(16);
const array = new Float32Array(buffer, 4, 3);

console.log(array.buffer === buffer); // true
console.log(array.buffer.byteLength); // 16
console.log(array.length * Float32Array.BYTES_PER_ELEMENT); // 12

// This incorrectly gets the full buffer:
console.log(new Uint8Array(array.buffer).length); // 16
// This gets the portion of the buffer corresponding to the Float32Array.
// The third parameter is array length, which for Uint8 is byte length.
console.log(new Uint8Array(array.buffer, array.byteOffset, array.byteLength).length); // 12

Try using the following code instead.

const base64String = encode(new Uint8Array(
  pcdRef.current.buffer,
  pcdRef.current.byteOffset,
  pcdRef.current.byteLength
));
Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • That was it exactly! Thank you. I would probably have stumbled around for days on that! – Joe Jul 24 '23 at 16:19