I promise this is my last post on primes for a while. (Sometimes one example leads to another, which leads to another, and so on.)

This example draws a bitmap to help visualize composite runs and prime numbers. The basic approach is similar to the one demonstrated by the example Use a bitmap to visualize primes in C#. Like the previous program, this example builds an Euler’s sieve to indicate which values are prime and which are composite. The difference is in how the two examples make a bitmap to represent the numbers.

The previous example represents primes in red and composite numbers in black. This example also represents primes in red. It represents a composite number in a shade of gray that depends on the number of composite numbers that came before it. If a composite number is the first in its run, it is colored black. If lots of composites come before this one, then it is colored with a lighter shade of gray.

The following code shows the `MakeBitmap` method that builds the bitmap. Blue text shows the code that was added to the previous example’s version of the method.

// Make a bitmap showing the primes. private Bitmap MakeBitmap(bool[] is_prime, int wid, int hgt) { // Make the bitmap. Bitmap bm = new Bitmap(wid, hgt); // Find the longest run length. int max_run_length = 0; int current_run_length = 0; for (int i = 0; i < is_prime.Length; i++) { if (is_prime[i]) { if (max_run_length < current_run_length) max_run_length = current_run_length; current_run_length = 0; } else current_run_length++; } // Get ready to calculate colors. float dc = 255f / (max_run_length - 1); // Set the pixels. int run_length = 0; int index = 0; for (int y = 0; y < hgt; y++) { for (int x = 0; x < wid; x++) { if ((index % 2 == 1) && (is_prime[index])) bm.SetPixel(x, y, Color.Red); else { byte c = (byte)(run_length * dc); bm.SetPixel(x, y, Color.FromArgb(c, c, c)); } if (is_prime[index]) run_length = 0; else run_length++; index++; } } // Fix 0, 1, and 2. (Assumes num_cols >= 3.) bm.SetPixel(0, 0, Color.Blue); bm.SetPixel(1, 0, Color.Blue); bm.SetPixel(2, 0, Color.Red); return bm; }

The first block of blue code loops through the `is_prime` array. It keeps track of the number of composite values in a row it has seen. When it reaches a prime number, the code records the composite run’s length if it is larger than the previous longest run and then resets the current run length to 0.

The code then sets `dc` to 255 divided by the length of the longest run. Later multiplying this value by a run length will give a value between 0 and 255.

The next line of blue code simply creates the `run_length` variable and sets it to 0.

The code then loops through the `is_prime` array, again keeping track of the current composite run length. When it finds a composite value, it multiplies `dc` by the current run length and uses the result to set the corresponding pixel’s color.

The result is long composite runs are colored with shades of gray that grow lighter as the runs get longer. Short runs are very dark so they are hardly noticeable. Long runs grow brighter and the longest runs end in white pixels.