Binary Operation Pictures
I thought it would be interesting to generate some pictures of binary operations.1 As we all know, there are 256 shades of monochrome.2 256 also happens to be a nice side length for an image to have. So given a function \(f\) that takes two natural numbers ranging from 0 (inclusive) to 256 (exclusive), a picture can be generated by coloring the pixel at \((x, y)\) the shade of monochrome corresponding to \(f(x, y)\). That is, \((f(x, y), f(x, y), f(x, y))\). One caveat is that the origin is at the top-left and \(y\) points down, as is standard for 2D graphics.
Warning: Some of the animations near the bottom may contain flashing images.
For example, here’s addition mod 256, which is a diagonal gradient, as expected, and multiplication mod 256, which actually gives an interesting pattern:
There are 4 classic arithmetic operations, so the other two should of course get pictures too. Subtraction is just flipped addition, and division has to be handled specially. If we just let \(f(x, y) = \lfloor x/y\rfloor\), then most resulting values will be less than, say, 16, and half the values will be 0, making the picture almost completely black. To spice things up a bit, the result is multiplied by 256 so the full monochrome range can be used effectively. Let’s also throw in a modulo picture for good measure.
Bitwise operations can also be done. The pictures for those look kind of fractal-ish in some cases:
As a matter of fact, let’s compare the result of bitwise AND to 0 and return 255 if equal and 0 otherwise. Let’s do the same for bitwise OR, but compare to 255:
Oh look! It’s a pair of right isosceles Sierpiński triangles! We can’t really do the same thing for bitwise XOR, because you’d just get a boring white diagonal line against a boring black background, since \(x\oplus y = 0\implies x = y\) (and \(x\oplus y = 255\implies x = 255 - y\), since \(0\le x, y < 256\)). However, we do get something interesting by comparing it to \(\lfloor 256/3\rfloor = 01010101_2 = 85\):
A Cantor set with aspect ratio 2! Changing this equals sign to a less-than sign also gives something interesting:
We can animate the value being compared to, resulting in some cool animations. Let \(t\) be the current frame of the animation. It goes from 0 to 255 and loops back around.
A flickering gliding Sierpiński triangle and a parameterized Cantor set! While animations are running, let’s also show some animations involving ternary operations.3
Let’s not forget bitwise operations.
-
If the pictures display weird, it’s because I’m using a trick that fakes drawing to multiple HTML canvases using one WebGL2 rendering context. There’s a browser limit of 8 contexts (16 on desktop), and rendering to an offscreen canvas and using drawImage() to copy to a real 2D canvas is extremely slow on Firefox. The trick involves rendering a screenwide canvas on top of everything, scrolling it to the appropriate position as the user scrolls, and drawing on it exactly where the fake canvases are. ↩
-
In classic 8-bit-per-channel encoding. There’s also 16-bit-per-channel and float encoding, but I’m not using that here as the pictures would be come unnecessarily way too big. ↩
-
The post title says “binary”, but that assumes a static image :) ↩