JavaScript Canvas Bit Manipulation
Written by Ian Elliot   
Monday, 09 August 2021
Article Index
JavaScript Canvas Bit Manipulation
Beyond 32 Bits

If you are going to work with bitmaps at the most basic level you have to know how to test and modify bit patterns. The reason is that each pixel is stored using a set of bits to record each of the color channels.. 

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas




  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
      Extract: Basic Paths 
      Extract: Bezier Curves 
  4. Stroke and Fill
      Extract: Stroke Properties 
      Extract: Fill and Holes
      Extract: Gradient & Pattern Fills 
  5. Transformations
      Extract: Transformations
      Extract: Custom Coordinates 
      Extract  Graphics State
  6. Text
      Extract: Text, Typography & SVG 
      Extract: Unicode 
  7. Clipping, Compositing and Effects
      Extract: Clipping & Basic Compositing 
  8. Generating Bitmaps
      Extract:  Introduction To Bitmaps
      Extract :  Animation 
  9. WebWorkers & OffscreenCanvas
      Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
      Extract: Bit Manipulation  
  11. Typed Arrays
  12. Files, blobs, URLs & Fetch
      Extract: Blobs & Files
      Extract: Read/Writing Local Files 
  13. Image Processing
      Extract: ImageData
      Extract: The Filter API
  14. 3D WebGL
      Extract: WebGL 3D **NEW!
  15. 2D WebGL
    Extract: WebGL Convolutions 







If you are going to work with bitmaps at the most basic level you have to know how to test and modify bit patterns. The reason is that each pixel is stored using a set of bits to record each of the color channels. You need to know how to manipulate bits. Bit manipulation in JavaScript is complicated by the way it attempts to be type free, but it can be done. One of the consequences of this type free approach is that numbers are always stored as 64-bit floating point values - i.e. double precision floating point.

Yes - that's correct, JavaScript doesn't have an integer type that you can make use of. When needed JavaScript will perform an internal conversion to a 32-bit value but you can't gain access directly to this integer and it is converted back to floating point format as soon as it is possible.

So JavaScript is different when it comes to bit manipulation but it is not that difficult. Let's see how it all works.

The Bitwise Operators

JavaScript has a number of operators designed to allow you to perform bit manipulation. There are four bitwise operators:





XOR (exclusive or)




As you would expect, the NOT operator has the highest priority.

Notice that there are also corresponding logical operators  &&, || and ! that only work with Boolean values and not bit patterns.

If you are more familiar with other languages you might well confuse ^ with raise to a power.

The bitwise operators work with numeric data which is converted from floating point to a 32-bit integer, operated on and then converted back to floating point. As a floating double can store a 32-bit integer without loss of precision everything works transparently as long as you stay within the 32-bit limit.

For example:

var a = 0xF0;
var b = 0xFF;
var c = ~a & b;

This first works out the bitwise NOT of a, i.e. 0F. This is then bitwise ANDed with b, i.e. 0F & FF, which is F. You should see the result 15 in decimal displayed. Bit manipulation is usually easiest to try out using hexadecimal notation with the results returned in decimal, 0xF is 15, or in binary, 0xF is 1111. There is no way of entering binary directly in JavaScript but you can use hex and octal and there is the paresInt function which will convert from a range of bases.

So what happens if you go over the 32-bit limit?

In fact, strange things start to happen before you reach the 32-bit limit because the 32-bit value is signed and this means that if the highest bit is 1 the returned value is negative.

For example:

var a = 0xFFFFFFF;
var b = 0xFFFFFFF;
var c = a & b;

displays 0xFFFFFFF, which is what you would expect. Notice that toString(16) converts the floating point number to a hex string.

Now try adding one more F to both values i.e. a full 32-bit value all set to 1. The result displays as -1 which might not be what you expect but it is perfectly correct.

The result of ANDing two full 32-bit values both set to 1 is a 32-bit value with all bits set to one but as the 32-bit value is interpreted as a signed value when converted to floating point this displays as -1 using two’s complement. 

You don't have to worry about this too much as the bit pattern corresponding to -1 is 32 bits all set to 1, so everything should carry on working if you use the value for further bit manipulation. That is, although it looks wrong it still works as far as bit manipulation is concerned.

Now consider what happens if you add one more F to the values. In this case the values are 36 bits, all set to 1 and the result should also be 36 bits, all set to 1. But no, both the a and b values are converted to 32-bit values, the two values are ANDed together and give a 32-bit result, i.e. -1 as before. You can’t do bit manipulation with more than 32 bits.

Last Updated ( Monday, 09 August 2021 )