# Bit masking (or not)?

**URL:** <https://discourse.processing.org/t/bit-masking-or-not/45177>\
**Category:** Processing.py\
**Created:** [October 14, 2024, 9:17am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177 "2024-10-14T09:17:50Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![paulstgeorge](https://avatars.discourse-cdn.com/v4/letter/p/53a042/32.png) [@paulstgeorge](https://discourse.processing.org/u/paulstgeorge)\
**Post date:** [October 14, 2024, 9:17am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/1 "2024-10-14T09:17:50Z")

</div>

I often see it said that bit masking is faster [1] than other simpler Processing methods. I also read that bit masking is not faster [2], and it comes with disadvantages such as extra lines of code and less clarity.

Is it still true that bit masking is faster in Python mode of Processing? Is there a way to measure and compare the speeds of say `float b1 = blue(c)` and `float b2 = c & 0xFF`?

[1]  
The blue() function is easy to use and understand, but it is slower than a technique called bit masking. When working in colorMode(RGB, 255), you can achieve the same results as blue() but with greater speed by using a bit mask to remove the other color components. For example, the following two lines of code are equivalent means of getting the blue value of the color value c:

```auto
float b1 = blue(c) // Simpler, but slower to calculate
float b2 = c & 0xFF // Very fast to calculate

```

> **[blue() / Reference](https://processing.org/reference/blue_.html)**
>
> Extracts the blue value from a color, scaled to match current colorMode(). The value is always returned as a float, so be careful not to assign it to an int value. The blue() …

[2]  
Note: Don’t use the bit shift operators as a means of premature optimization in Python. You won’t see a difference in execution speed, but you’ll most definitely make your code less readable.

> **[Bitwise Operators in Python – Real Python](https://realpython.com/python-bitwise-operators/)**
>
> In this tutorial, you'll learn how to use Python's bitwise operators to manipulate individual bits of data at the most granular level. With the help of hands-on examples, you'll see how you can apply bitmasks and overload bitwise operators to control...

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 17, 2024, 11:39pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/2 "2024-10-17T23:39:21Z")

</div>

Hello @paulstgeorge,

To optimize or not to optimize?  
This very much depends on what you are doing.

If you are processing pixels in video frames in real-time (quickly enough to keep up with the incoming video) you will certainly want to optimize.

> [@paulstgeorge](#):
>
> I also read that bit masking is not faster [2]

Your [2] states:

> [@paulstgeorge](#):
>
> You won’t see a difference in execution speed

_ **You will not see a difference** _ with a single execution of the statements you provided.

_ **You will see a difference** _ if you are running it in a loop and measure the time for multiple executions.

Example:

```auto
t0 = millis();
for i in range(0xFFFFFF):
    b1 = blue(i);
t1 = millis()
println(t1-t0);

t0 = millis();
for j in range(0xFFFFFF):
    b2 = j & 0xFF
t1 = millis()
println(t1-t0);

```

Output:  
2007  
1406

`:)`

---

<div class="post-metadata">

**Author:** ![paulstgeorge](https://avatars.discourse-cdn.com/v4/letter/p/53a042/32.png) [@paulstgeorge](https://discourse.processing.org/u/paulstgeorge)\
**Post date:** [October 18, 2024, 6:43am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/3 "2024-10-18T06:43:10Z")

</div>

That’s great, thank you. Your explanation and demonstration should be in the documentation.

PS I made a third clumsy comparison because to use bit shifting, the numbers often have to be converted from floats to integer. Then bit shifting method is slower than `b1 = blue(i)` [as that simpler method can handle floats].

But your use of a timer enables people to test for themselves and then make an informed choice!

```auto
def setup():
    noLoop()

def draw():
    t0 = millis()
    for i in range(10000000):
        j = float(i)
        k = int(j)
        b3 = k & 0xFF
        
    t1 = millis()
    print(t1-t0)

```

---

<div class="post-metadata">

**Author:** ![eightohnine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/eightohnine/32/19793_2.png) [@eightohnine](https://discourse.processing.org/u/eightohnine)\
**Post date:** [October 18, 2024, 8:51am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/4 "2024-10-18T08:51:53Z")

</div>

My spontaneous guess was that blue() is just a beginner-friendly wrapper around a bitwise operation? After all, you don’t want to scare off coding newcomers with talks of bit shifting and masking.

I checked in the [PApplet.java source](https://github.com/benfry/processing4/blob/main/core/src/processing/core/PApplet.java) to see if my hunch was confirmed. But… this is strange, blue() is set up as follows, not as a bit mask.

```auto
public final float blue(int rgb) {
   return g.blue(rgb);
}

```

Though in this case _g.blue()_ method references the current PGraphics renderer (signified by g). Let’s check out the [PGraphics.java source](https://github.com/benfry/processing4/blob/main/core/src/processing/core/PGraphics.java):

```auto
public final float blue(int rgb) {
    float c = (rgb) & 0xff;
    if (colorModeDefault) return c;
    return (c / 255.0f) * colorModeZ;
}

```

And here we have it.

Bottom line, wrapping that bitwise operation into function call(s) overhead will clearly take longer than applying it directly. Though as @glv states nicely, any significant time gain is fully dependent on what you’re building.

It’s the Processing-typical **Trading Power for Accessibility** -compromise.

---

<div class="post-metadata">

**Author:** ![eightohnine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/eightohnine/32/19793_2.png) [@eightohnine](https://discourse.processing.org/u/eightohnine)\
**Post date:** [October 18, 2024, 3:15pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/5 "2024-10-18T15:15:47Z")

</div>

Well, duh… so much for not seeing the forrest for the trees. Just noticed now, that this whole topic is about Processing.py. 🤦‍♂️

Though I assume that my general sentiment is still applicable in this context.

---

<div class="post-metadata">

**Author:** ![paulstgeorge](https://avatars.discourse-cdn.com/v4/letter/p/53a042/32.png) [@paulstgeorge](https://discourse.processing.org/u/paulstgeorge)\
**Post date:** [October 18, 2024, 3:46pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/6 "2024-10-18T15:46:58Z")

</div>

> [@eightohnine](#):
>
> Though I assume that my general sentiment is still applicable in this context.

Absolutely.

And yes, Processing is great for non-programmers (like me)!

> [@eightohnine](#):
>
> It’s the Processing-typical **Trading Power for Accessibility** -compromise.

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 26, 2024, 11:26am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/7 "2024-10-26T11:26:10Z")

</div>

> [@paulstgeorge](#):
>
> Then bit shifting method is slower than `b1 = blue(i)` [as that simpler method can handle floats].

In this example I am comparing 3 methods:

```auto
def setup():
    size(600, 600);
    background(0);

def draw():
    
    n = 3000000  
    
# Method 1 (custom)  
        
    t0 = millis()
    for i in range(n):
        j = float(i) 
        k = int(j)
        b3 = k & 0xFF # 1: bit masking after 2 casts (to float and then int)
        
    t1 = millis()
    d1 = t1-t0
    print(1, d1)
    
# Method 2   
    
    t0 = millis()
    for i in range(n):
        b3 = blue(i) # 2: Using blue()
        
    t1 = millis()
    d2 = t1-t0
    print(2, d2)    
    
# Method 3
       
    t0 = millis()
    for i in range(n):
        b3 = i & 0xFF # 3: Bit masking
        
    t1 = millis()
    d3 = t1-t0
    print(3, d3)    
    
    print(" ")    

    strokeWeight(3);
    x = 3*frameCount;
    stroke(255, 0, 0)
    point(x, d1)
    stroke(255, 255, 0)
    point(x, d2)
    stroke(0, 255, 0)
    point(x, d3)

```

Method 3 (green) is the fastest (bit masking directly on an integer):

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/c/3/c3bb5a373fb2a5c755a878bc61f8302a26305b23.png)

It is important to do multiple tests to clearly see the differences.

`:)`

---

<div class="post-metadata">

**Author:** ![paulstgeorge](https://avatars.discourse-cdn.com/v4/letter/p/53a042/32.png) [@paulstgeorge](https://discourse.processing.org/u/paulstgeorge)\
**Post date:** [October 27, 2024, 10:00am UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/8 "2024-10-27T10:00:57Z")

</div>

@glv That’s great! An excellent way to demonstrate the different speeds.

It is very clear that method 1 is far slower than either method 2 or method 3. So is this the fuller story? Bit-masking could be faster than blue() when you don’t need to cast the numbers to integers before using?

 ![speed](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/9/4/94f09e83b245e7a747210e19467625ab118fd658.png)

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 27, 2024, 1:08pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/9 "2024-10-27T13:08:46Z")

</div>

Hello @paulstgeorge,

Your picture did not show the code for the method used and I can’t comment on that.

> [@paulstgeorge](#):
>
> Bit-masking could be faster than blue() when you don’t need to cast the numbers to integers before using?

Bit masking is faster than `blue()` and is clearly stated here:

> **[blue() \\ Language (API)](https://py.processing.org/reference/blue)**
>
> Python Mode for Processing extends the Processing Development Environment with the Python programming language.

Colors are stored as 32 bit integers.  
If you are working in the default mode _colorMode(RGB, 255)_ and you want to optimize code for image editing then stick to using _ **integers** _, _ **bit manipulation** _ and _ **replace the helper functions** _ for extracting and setting colors.

\*\*\* Edited the above for clarity on intended context. \*\*\*

You can see what is done under the hood in the source code and can remove the bloat and customize for your project.

Extraction:  
[red()](https://github.com/processing/processing/blob/master/core/src/processing/core/PGraphics.java#L7934)  
[green()](https://github.com/processing/processing/blob/master/core/src/processing/core/PGraphics.java#L7967)  
[blue()](https://github.com/processing/processing/blob/master/core/src/processing/core/PGraphics.java#L8000)

Setting:  
[color(v1, v2, v3)](https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L10426)

If you add code to cast or wrap it in a function it will add to the execution time.

The `blue()` function returns a float for any colorMode and NOT optimized for _colorMode(RGB, 255)_ :  
`print(type(blue(0x00FF00))); // Console: <type 'float'>`

Color is an int:  
`print(type(color(255, 0, 0)) // Console: <type 'int'>`

Thee may be exceptions where the compiler optimizes code but that is another discussion.

My roots are in the embedded world and bit manipulation is second nature to me.  
I find the helper functions in Processing and Arduino abstract away from what is really going on under the hood. They are great for a beginner programmer but can be [cumbersome](https://www.google.com/search?q=cumbersome) for an experienced programmer.

Reference:  
_[Core Embedded Systems Skill: Bitwise Operation | by Alwin Arrasyid | Medium | Medium](https://alwint3r.medium.com/core-embedded-systems-skill-bitwise-operation-17259cfb670f)_

A good tutorial that also has bit manipulation with comments on why it is used:

> **[Color Gradients in Processing (v 2.0)](https://behreajj.medium.com/color-gradients-in-processing-v-2-0-e5c0b87cdfd2)**
>
> This tutorial on color gradients is an overhaul of a prior version; hopefully it will prove more useful to creative coders who wish to work…

`:)`

---

<div class="post-metadata">

**Author:** ![paulstgeorge](https://avatars.discourse-cdn.com/v4/letter/p/53a042/32.png) [@paulstgeorge](https://discourse.processing.org/u/paulstgeorge)\
**Post date:** [October 27, 2024, 2:25pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/10 "2024-10-27T14:25:46Z")

</div>

Hi! Its your code. Sorry, I should have said.

> [@glv](#):
>
> stick to using _ **integers only** _,

This conversation came out of the discussion: [Color to grayscale algorithm](https://discourse.processing.org/t/color-to-grayscale-algorithm/45171)

The widely used algorithms mentioned have floats for RGB values. For example,  
`Luminance = 0.2126 * Red + 0.7152 * Green + 0.0722 * Blue`

I’ll read the Medium articles with great interest. Thank you!

---

<div class="post-metadata">

**Author:** ![glv](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/glv/32/18785_2.png) [@glv](https://discourse.processing.org/u/glv)\
**Post date:** [October 27, 2024, 4:56pm UTC](https://discourse.processing.org/t/bit-masking-or-not/45177/11 "2024-10-27T16:56:33Z")

</div>

> [@paulstgeorge](#):
>
> The widely used algorithms mentioned have floats for RGB values. For example,  
> `Luminance = 0.2126 * Red + 0.7152 * Green + 0.0722 * Blue`

The R, G and B did not need to be floats and can be efficiently extracted from the color integer with bit manipulation.  
The luminance will be a float.  
You may need to use floating point math in such cases and can cast results as required.

I edited my previous post for clarity on context.

@solub made some approximations [here](https://discourse.processing.org/t/color-to-grayscale-algorithm/45171/5) to optimize performance:

> [@Color to grayscale algorithm](https://discourse.processing.org/t/color-to-grayscale-algorithm/45171/5):
>
> ```auto
> # Calculate the true relative luminance using scaled weights:
> # Luminance = 0.2126 * Red + 0.7152 * Green + 0.0722 * Blue
> # Approximation: 0.2126 * 256 = 54, 0.7152 * 256 = 183, 0.0722 * 256 = 18
> lum = (54 * r + 183 * g + 18 * b) >> 8 # Bit-shift by 8 (dividing by 256)
> 
> ```

There are also examples of extracting and setting colors without the helper functions:  
_[Color to grayscale algorithm - #5 by solub](https://discourse.processing.org/t/color-to-grayscale-algorithm/45171/5)_

`:)`
