Instead of working this way why not simply scan through the array in any order and work out the i,j value that the index corresponds to in the bitmap. Then work out the x,y value that the i,j value corresponds to in the Mandelbrot set. That is we can use the inverse storage mapping functions and just work our way through the byte array computing the pixel data at each location.

That is the location:

wbmap.Pixels[i]

corresponds to the pixel at px,py in the bitmap as given by:

int py = i / s;int px = i % s;

Notice that the division is integer division which truncates to the nearest lower integer.

Now that we have the position in the bitmap we can convert this to the location in the Mandelbrot set. This is just a case of a simple scaling and translation to map the rectangle (0,0) (PixelWidth,PixelHeight) into the rectangle (-2.4, -1.5) (0.8, 1.5). A little algebra gives

x=px*(-1.5 + 2.4)/PixelWidth-2.4y=0.8 - py*(1.5-0.8)/PixelHeight

If you are puzzled as to why the y expression seems to have an extra minus in it - the reason is that the bitmap y co-ordinate py increases down the screen but the usual y co-ordinate increases up the screen.

Of course these expressions are in terms of the particular rectangle that we are plotting. A more general expression can be written using the Rect area we defined earlier:

Notice that we are stepping through the array by the number of bytes needed to deal with one entire pixel each time through the loop. Although we could roll all of the co-ordinate transformation up into one big expression debugging is easier with them split into smaller logical units. First the pixel co-ordinates:

int py = i / s;int px = i % s;

then the x,y co-ordinates from the pixel co-ordinates:

double x = area.Left + px * xscale;double y = area.Top - py * yscale;

Now we have x,y it s possible to call the method that discovered if the point is in the Mandelbrot set or not:

Complex c = new Complex(x,y);int count= mandelbrot(c);

The return value of count is going to use it to set the pixel's color.

How exactly to do this?

The four pixels starting at pixels[i] give the R, G, B, A components of the color respectively as byte values. Now we could use a method to map the count to a set of colors using a table say. However, given that we have been using so many storage mapping functions, we might as well use another one.

The idea is to think of the count, which varies from 1 to 1000, as 1000 different colors arranged in a line. Now consider the RGB color space as a cube of 10x10x10 different colors. The storage mapping function we need maps the 1000 linear colors to the rows, columns and layers of the RGB cube. More commonly the requirement is to map a 3D storage cube to a linear array but the inverse storage mapping functions map the cube to the array and this is what we need. A method to convert a count in the range 1 to 1000 to color values evenly spread across the RGB cube is:

The initial co-ordinates give a good view of the entire Mandelbrot set from which the user can pick an area to zoom in on. Initially the zoom area is set to the entire display, which means no zoom is applied. Finally notice that you do need a button called “Reset” on the form to activate this initialisation routine manually - and this is our next task.