4

Let's say I have an Uint8Array of 4096 items where each of them is the value 0xff or 255. I want to convert this array into a Float64Array where 8 values of the previous array correspond to a one 64-bit float. I have tried this code:

 // Every item is 1 byte in pixels array, I want 8 of them to represent
 // a 64-bit float in the float64Array
 let pixels = new Uint8Array([255, 255, 255 ... , 255]); // 4096 values
 let floatArr = new Float64Array(pixels.buffer); // Should be 512 values
 console.log(floatArr); // This shows NaNs all over.

I have seen couple more questions that seem to be close what I am asking, but I could not get the idea from the answers provided to them. After inspecting Mozilla documentation, this seemed to me the correct way of using, however, I am not getting the expected result. How can I make this happen? Also, I am limited to the browser, you can assume the latest versions.

Edit: The expected result for a sample run is:

// pixels array is the input
let pixels = new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); // 16x 0xff, 16 bytes
let floatArr = new Float64Array(pixels.buffer) // I expect this to be
// [0xffffffffffffffff, 0xffffffffffffffff] which is 8bytes x 2,
// Float64Array [ 18446744073709552000, 18446744073709552000 ]
6
  • Can you add a sample 8 element input and expected output? Commented Dec 12, 2018 at 1:27
  • I have added a sample input and an expected output, I hope it is helpful Commented Dec 12, 2018 at 1:36
  • Based on your expected output, try BigUint64Array Commented Dec 12, 2018 at 1:45
  • 2
    ..waking up, but it seems it's because your Uint8Array full of 255 can not be represented as Float64 in 32bits IEEE 754 (what js uses to represent numbers) But the data in the ArrayBuffer should still be there as expected. Why do you want to use a Float64Array exactly? If by the name of your variable you are dealing with an ImageData's data and are willing to perform faster pixel manips, then stick to UInt32Array, each pixels its slot makes the more sense. Commented Dec 12, 2018 at 1:49
  • 1
    Your confusion seems to be in the binary representation of Float64. Essentially the code you have is equivalent to C++ uint8_t pixels[] = ...; auto floatArr = reinterpret_cast<double[]>(pixels);. Commented Dec 12, 2018 at 2:05

1 Answer 1

4

Take a look at e.g. https://en.wikipedia.org/wiki/NaN

IEEE 754 NaNs are represented with the exponent field filled with ones (like infinity values), and some non-zero number in the significand (to make them distinct from infinity values); this representation allows the definition of multiple distinct NaN values, depending on which bits are set in the significand, but also on the value of the leading sign bit (but applications are not required to provide distinct semantics for those distinct NaN values).

So basically, you have created an array of NaNs.

To successfully create a Float64Array from an uint8array buffer you need to ensure that the buffer contains valid representations of 64 bit floats e.g.

// pixels array is the input
let pixels = new Uint8Array([ 174,71,225,122,20,174,40,64]); // Float64Array([12.34]).buffer
let floatArr = new Float64Array(pixels.buffer) // I 
console.log(floatArr) // 12.34

Even with that being said, you probably don't want to use a Float64Array anyway, since the buffer conversion of color pixel values are unlikely to create any meaningful numbers. (And at least in something like C you'd risk creating trap representations, not sure how thats handled in JS)

In the comments someone suggested BigUint64Array which would get around the NaN and trap representations. But I think that is still only available in Chrome.

And as pointed out below by Kaiido, a Uint32Array will hold your 4 color channels for each pixel, so unless you are trying to do some magic where you need to integrate pixels pairwise, a 32 bit typed array is what you want.

Sign up to request clarification or add additional context in comments.

6 Comments

I am tempted to upvote because the first part is clear-point into the problem (and if they had a sequence of 0, 0, 0, 0, 0, 0, 240, 127, then they would have seen Infinity) ; but the second part lost me... In one hand you talk about the need to choose a correct representation, but just after, the code snippet shows a modified dataset which proves nothing. Are you really advising them to change their dataset? Ps: given the name of the variable, we can presume that it is an array of RGBA pixel values, for which an Uint32Array would be the best representation if channels are not important
@Kaiido, I'll try to edit to clarify it. My point was to point to what the problem was, then the code example as to what a successful conversion looks like. Then finally I tried to make the point, that with all that being said, it still doesn't make much sense to convert pixel values into a float array, unless you are also normalizing or something. The only motivation I can see, is if the OP is hoping to do bit manipulation cross the color channels and hoping to use float64array as just a temporary container
Ok sounds better to me. I would probably personally have chosen to make a snippet showing how you can force different values such as other NaN or Infinity to prove the point, i.e the other way around, but that may be just me.
Hey, just to clear things a bit, I am not doing any meaningful pixel manipulation. What I do is a gpu based row hammer attack. I try to check if my bit flip is in the first 25-bits so that I can conclude it is exploitable. This is the attack vusec.net/projects/glitch. In any way, your answers are very hepful.
@Kaiido, yes, I was confused about some points related to JS which this answer made clear to me.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.