4
var rgba = 0xFFFFFFFF;
console.log((rgba&0xFF000000)>>24);

The snippet above displays -1 instead of 255, which makes no sense. I'm aware JS numbers are float64 and thus you can't expect precise binary operations above certain point, but is that point so low you can't represent a RGBA channel in a single number?

MaiaVictor
  • 51,090
  • 44
  • 144
  • 286
  • 6
    Sign / unsigned issue. I think using the ">>>" operator does unsigned. – Marvin Smit Nov 24 '13 at 13:23
  • @MarvinSmit: indeed: `0xFF000000 >>> 24 === 255` – Qantas 94 Heavy Nov 24 '13 at 13:24
  • Oh, interesting, thank you. What is the limit of the size I can store data in a single number without breaking the precision? (I just tested 0xFF000000>>>32) and it does not work!) – MaiaVictor Nov 24 '13 at 13:24
  • http://stackoverflow.com/questions/307179/what-is-javascripts-max-int-whats-the-highest-integer-value-a-number-can-go-t answer that one i think – Marvin Smit Nov 24 '13 at 13:26
  • @Roya. Highest bit represents the positive/negative flag. ASR of 0xFF00 = 0x807F, LSR of 0xFF00 = 0x00FF. – Marvin Smit Nov 24 '13 at 13:28
  • 2
    @Viclib, you can store integers up to 53 bits in a single javascript number variable without loss of precision, but you can't do bitwise operations (like bit shifting) on them, as bitwise operations convert to 32 bits. – kybernetikos Dec 05 '13 at 23:22

1 Answers1

2

This is not actually a precision issue.

In javascript bitwise operators convert their arguments to 32bit signed values. In 32bit signed form &ff000000 is a negative number, so when you shift it, the bits that come in on the left are 1s instead of 0s (this is to ensure that a twos complement negative number remains negative after shifting). You can still get the behaviour you want by bitwise anding with 0xff after the bitshift, which if you're pulling out the different colour components is probably the best thing to do anyway.

var rgba = 0xFFFFFFFF;
console.log((rgba>>24)&0xff);

var red = (rgba>>24) & 0xff;
var green = (rgba>>16) & 0xff;
var blue = (rgba>>8) & 0xff;
var alpha = rgba & 0xff;

As Marvin Smit mentions above, >>> is an unsigned right shift which always pulls in 0s, so in this specific case you could use that too. Wikipedia describes them as 'arithmetic' and 'logical' right shifts.

kybernetikos
  • 8,281
  • 1
  • 46
  • 54