Fun with Flags, Enums and Bit Shifting
Tags: dotnet, csharp
Published: 2021-12-08 06:49:01

While thinking of posts to write about, the title "Fun with Flags" came to mind [from a certain TV show](https://www.youtube.com/watch?v=Xl12Sp1KiEk) and I wondered how I might connect that to programming. There are _enum flags_ in C# via the [`Flags` attribute](https://docs.microsoft.com/en-us/dotnet/api/system.flagsattribute?view=net-5.0#remarks) so maybe that was something I could write about. That said, I wanted to do something more creative than some humdrum post about using enums even if the end result isn't really practical.

Instead I decided to make _real_ flags in C# with enums - turning a number like `52357729848` into a flag:

![The German Flag](https://funwithflags.turnerj.com/api/flag/generate.png?v=52357729848)

A gave myself certain requirements:
- I needed to be able to generate more than one flag
- I wanted to encode everything about the flag in a single value via enums

There are technical limitations too as I can't store a lot of data in an enum and will need to make compromises. An enum can be backed by a few different types but I chose `long` so I could get a full 64-bits of data to play with.

## Encoding a Value

My initial thought with this was to pick the easiest form of flag - simple flags with stripes. If I split a typical flag into 9 segments, maybe I can store 9 colours and that would allow drawing of horizontal and vertical stripes. It seemed like the most straightforward approach at the time (I realised later it might have been better if I stored "shape" data instead for more flag variety but _oh well_).

The problem is, storing 9 segments in 64 bits is pretty hard and would leave me with about 7.11-bits per segment making colour data very limited. I wanted 3 colour channels so that only gives me really 2-bits per colour which is not a lot of variety. Having then 6-bits per segment, it left me with 10-bits that I don't really have much use for. Initially I tried using those bits to help extend the range of colours, acting as a multiplier for a specific channel. In the end though, it wasn't overly useful for this so I cut it.

This is the data structure I ended with:

```csharp
[PPPPPPPPPP]
[RRGGBB][RRGGBB][RRGGBB]
[RRGGBB][RRGGBB][RRGGBB]
[RRGGBB][RRGGBB][RRGGBB]

P = Padding
R = Red Intensity
G = Green Intensity
B = Blue Intensity
```

My primary data only takes 54-bits so my data structure has 10-bits of padding at the front. Having the padding at the front allows the generated number to be smaller.

I will be using [ImageSharp](https://github.com/SixLabors/ImageSharp/) for converting this value into an actual image. Because I have 9 segments, it seemed like the best idea to treat the image as a 3x3 pixel square and get ImageSharp to resize it for me. The pixel format for the data though was RGB24 so I needed to work out how to scale up my colours from 2-bits to 8-bits per channel.

With 8-bits, the max value I can have is 255 for a single channel.
Full colour intensity for any channel is 3 so I decided to simply divide the max value by the full colour intensity leaving me the magic number of 85 to scale my values by.

That is the nuts-and-bolts of the format, now it was just to make that work in code.

## A Bit Shifty

Knowing I can store the data is one thing, actually making it work was another. I don't often use [bitwise and shift operators](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators) but for this, it was going to use them quite heavily.

Firstly, we need an enum of colour intensity values:

```csharp
public enum Intensity : byte
{
	None = 0,
	OneThird = 1,
	TwoThirds = 2,
	Max = 3
}
```

The specific values here are important because of what they represent in binary.

```csharp
00000000 // Intensity.None
00000001 // Intensity.OneThird
00000010 // Intensity.TwoThirds
00000011 // Intensity.Max
```

Because these values represent a single channel's intensity, we need to combine 3 of them together to form our full colour. We combine them by using bit shifting and bitwise OR operations to create our 6-bit colour value.

```csharp
public enum Colour : long
{
	Black = 0,
	Red = Intensity.Max << 4,
	Green = Intensity.Max << 2,
	Blue = Intensity.Max,
	White = Red | Green | Blue
}
```

While we are using a `long` here (helping us with our later bit shifting operations), the values we are setting fit within 6-bits. Viewing the colours as bytes in binary, the shifting and OR-ing of data would look a little like this:

```csharp
00110000 // Red = Intensity.Max << 4
00001100 // Green = Intensity.Max << 2
00000011 // Blue = Intensity.Max
00111111 // White = Red | Green | Blue
```

Using different intensity values for the different colour channels, we can create new colours too.

```csharp
00110000 // Red = Intensity.Max << 4
00001000 // Green = Intensity.TwoThirds << 2
00000000 // Blue = Intensity.None
========
00111000 // Yellow = (Intensity.Max << 4) | (Intensity.TwoThirds << 2)
```

To create a few different types of flags, we will need a few more colours...

```csharp
public enum Colour : long
{
	Black = 0,
	Red = Intensity.Max << 4,
	Green = Intensity.Max << 2,
	Blue = Intensity.Max,
	White = Red | Green | Blue,
	Orange = (Intensity.Max << 4) |
		(Intensity.OneThird << 2),
	Yellow = (Intensity.Max << 4) |
		(Intensity.TwoThirds << 2),
	MediumGreen = Intensity.TwoThirds << 2,
	LightBlue = (Intensity.TwoThirds << 2) |
		Intensity.Max,
	DarkBlue = Intensity.OneThird
}
```

Identifying the right combinations of values for colours was relatively straight forward - I used an RGB colour picker in [Paint.NET](https://www.getpaint.net/) and selected thirds of the different colour channels. Like if I had two thirds red and one third green, I'd approximately have orange.

![Colour picker showing 2 thirds red and 1 third green](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxm3j5ttctl73xhiwo37.png)

So now we've got our colours, we need to encode the final value of a flag. In a similar approach to combining the colour channels, we need to combine the colours of the 9 segments by shifting and OR-ing.

```csharp
public enum CountryFlags : long
{
	Germany = Colour.Black << 48 | Colour.Black << 42 | Colour.Black << 36 |
		Colour.Red << 30 | Colour.Red << 24 | Colour.Red << 18 |
		Colour.Yellow << 12 | Colour.Yellow << 6 | Colour.Yellow
}
```

While `Colour.Black` does encode as `0` so the first 3 values aren't actually needed, it made it easier to still think of it as 9 distinct segments that all needed colours set.

In binary, the operation to encode our German flag would look like:

```csharp
        00000000 // Black, shifted by 48-bits
              00000000
                    00000000
                          00110000 // Red, shifted by 30-bits
                                00110000
                                      00110000
                                            00111000 // Yellow, shifted by 12-bits
                                                  00111000
                                                        00111000
================================================================
0000000000000000000000000000110000110000110000111000111000111000
```

As a decimal, that would be `52357729848`. This is only half the job though, we have our flag data as number but we also need to decode it to an image.

## Generating an Image

So how do we take `52357729848` and turn it into an image? We use more bit shifting and now AND-ing of our data to get each individual colour. Also, we will be reading the data in reverse.

```csharp
var blueComponent = (byte)(flagData & 3) * 85;
```

The value `flagData` here is a `long` of our generated number.

To get the blue component, we don't need to shift but we do need to perform a logical AND of the data. We only want the last two bits of the number - if we just convert the number to a byte, we will get the last 8-bits.

```csharp
0000000000000000000000000000110000110000110000111000111000111000
                                    // We only want this part ^^
```

By doing `flagData & 3`, we get just the last 2-bits from the full value. To get the next components, we do the same but now on a bit shifted value so the last 2-bits are of the colour we want.

```csharp
var greenComponent = (byte)((flagData >> 2) & 3) * 85;
var redComponent = (byte)((flagData >> 4) & 3) * 85;
```

Now we have the 3 colour channels of the bottom right segment of our flag. As a reminder, the 85x multiplier is to adjust the colour to fit within a full 8-bits for the RGB24 pixel format. Really now, it is just a matter of wrapping the code within some loops to set it to an image.

```csharp
using var image = new Image<Rgb24>(3, 3);
for (var y = 2; y >= 0; --y)
{
    for (var x = 2; x >= 0; --x)
    {
        var pixel = image[x, y];
        var blueComponent = (byte)((flagData >> 0) & 3) * 85;
        pixel.B = (byte)blueComponent;
        var greenComponent = (byte)((flagData >> 2) & 3) * 85;
        pixel.G = (byte)greenComponent;
        var redComponent = (byte)((flagData >> 4) & 3) * 85;
        pixel.R = (byte)redComponent;
        flagData >>= 6;
        image[x, y] = pixel;
    }
}
```

In our inner-most loop, we also shift our bits in `flagData` over 6-bits so we are in the next segment for the next iteration. This code though would only leave us with a 3x3 flag which doesn't look right so with a little more code, we can make it be bigger and more flag-like.

```csharp
image.Mutate(x => x.Resize(400, 240, new NearestNeighborResampler()));
```

The `NearestNeighborResampler` here is important - it allows us to scale up our specific "blocky" image here without distorting or blurring it.

And that's basically it - we can take a bunch of enums and encode a value then take the value and decode it to an image. I've set up an Azure Function running this code to show it working and few flags I've generated:

`https://funwithflags.turnerj.com/api/flag/generate.png?v=ENCODED_VALUE`

### Germany

Value: [52357729848](https://funwithflags.turnerj.com/api/flag/generate.png?v=52357729848)
```csharp
Germany = Colour.Black << 48 | Colour.Black << 42 | Colour.Black << 36 |
	Colour.Red << 30 | Colour.Red << 24 | Colour.Red << 18 |
	Colour.Yellow << 12 | Colour.Yellow << 6 | Colour.Yellow,
```

### Italy
Value: [2532184938287088](https://funwithflags.turnerj.com/api/flag/generate.png?v=2532184938287088)
```csharp
Italy = Colour.MediumGreen << 48 | Colour.White << 42 | Colour.Red << 36 |
	Colour.MediumGreen << 30 | Colour.White << 24 | Colour.Red << 18 |
	Colour.MediumGreen << 12 | Colour.White << 6 | Colour.Red,
```

### France
Value: [561852585091056](https://funwithflags.turnerj.com/api/flag/generate.png?v=561852585091056)
```csharp
France = Colour.DarkBlue << 48 | Colour.White << 42 | Colour.Red << 36 |
	Colour.DarkBlue << 30 | Colour.White << 24 | Colour.Red << 18 |
	Colour.DarkBlue << 12 | Colour.White << 6 | Colour.Red,
```

### Ireland
Value: [2532459817242612](https://funwithflags.turnerj.com/api/flag/generate.png?v=2532459817242612)
```csharp
Ireland = Colour.MediumGreen << 48 | Colour.White << 42 | Colour.Orange << 36 |
	Colour.MediumGreen << 30 | Colour.White << 24 | Colour.Orange << 18 |
	Colour.MediumGreen << 12 | Colour.White << 6 | Colour.Orange,
```

### Luxembourg
Value: [13725272368788171](https://funwithflags.turnerj.com/api/flag/generate.png?v=13725272368788171)
```csharp
Luxembourg = Colour.Red << 48 | Colour.Red << 42 | Colour.Red << 36 |
	Colour.White << 30 | Colour.White << 24 | Colour.White << 18 |
	Colour.LightBlue << 12 | Colour.LightBlue << 6 | Colour.LightBlue,
```

## Final Thoughts

What started out as a bit of a weird challenge I set myself turned into a fun and interesting learning experience. I rarely mess around with bit shifting and bitwise operations. While I still probably won't need to very often, I like that I know a lot more about them now.

If I were to approach this again, I'd probably look at encoding shapes instead of pixels of colours. That way I could encode a wider variety of flags like the flags of Sweden, Japan and perhaps even South Korea.

### If you liked this...

If you liked the kinda strange and interesting nature of this, you might like my deep dive into Levenshtein Distance and the various optimizations.

- [Levenshtein Distance (Part 1: What is it?)](https://turnerj.com/blog/levenshtein-distance-part-1-what-is-it)
- [Levenshtein Distance (Part 2: Gotta Go Fast)](https://turnerj.com/blog/levenshtein-distance-part-2-gotta-go-fast)
- [Levenshtein Distance (Part 3: Optimize Everything!)](https://turnerj.com/blog/levenshtein-distance-part-3-optimize-everything)
- [Levenshtein Distance with SIMD](https://turnerj.com/blog/levenshtein-distance-with-simd)