Hemme's Blog

Stories from behind the keyboard

  • RSS
  • Twitter
  • Linkedin

When time permits, I like to experiment mixing some old algorithm and new technologies. This time it was up to Mandelbrot fractals generation (an old algorithm) and the WebMatrix (a new application development tool) plus Razor (a new templating engine for ASP.NET web pages). In effect, the Mandelbrot set is a well-known geometric guy, but it never ends to amaze me, especially when it’s time to figure out and try new coloring algorithms. This time it was also the occasion to practice the Razor syntax inside a vanilla WebMatrix project.

imageThe solution

My solution is built around two methods: the Mandelbrot fractal algorithm and a PNG picture generator, that creates a colored image from the fractal data generated by the former algorithm. Both methods are described ahead in this post. The home page Default.cshtml is a simple HTML page, including an <div id=”mandel” /> tag that will host the fractal image.

<!DOCTYPE html>
<html lang="en">     
<head>
        <meta charset="utf-8" /> 
        <title>Razor Mandelbrot Generator</title>
        <script src='@Href("~/Scripts/jquery-1.4.4.min.js")' type='text/javascript'></script> 
    </head> 
    <body>  
        <h1>Razor Mandelbrot Generator</h1>  
        <div id="mandel">@H.MandelbrotHtmlImage(w,h,minR,maxR,minI,maxiter)</div>  
        <!--Zoom box will go here-->
    </body>  
</html>
An <img /> tag will go inside the div#mandel and it’s build by an helper snippet declared in an /App_Code/H.cshtml file, as follows:

@helper MandelbrotHtmlImage(int w, int h, double minr, double maxr, double mini, int maxiter)
{
  <img alt="Mandelbrot Fractal" src="@Href("~/Get?w=" + w + "&h=" + h + "&maxiter=" + maxiter + "&minr=" + minr + "&maxr=" + maxr + "&mini=" + mini)" />
}
As you can see, the image’s href is a request to a Get “page” – in effect WebMatrix will route the request to a Get.cshtml file, as described here). This request gives the page all the parameters it needs to create a fractal image (more details ahead).

Getting the fractal image as a binary stream

The Get.cshtml page does tree things:

  1. Calculating the fractal data
  2. Building and coloring a PNG image from the fractal data
  3. Returning the image as a binary stream
The first and the last tasks are accomplished invoking helper @functions declared inside H.cshtml. The following code is the main fragment of Get.cshtml:

//The Get.cshtml main fragment:

@{
    var data = H.GetMandelbrotSet(w,h,minR,maxR,minI,maxiter);

    var img = new Bitmap(w, h); 
 
   // The coloring algorithm stuff
   // ...

   var ram = new MemoryStream();
   img.Save(ram,ImageFormat.Png);
   ram.Seek(0, SeekOrigin.Begin);
   H.BinaryResponse(ram, String.Format("mandel_{0}_{1}_{2}.png", minR, maxR, minI), "image/png");
}
Starting from the bottom,  the BinaryResponse() method is a @function declared inside H.cshtml page, as follows:

@functions {
  public static void BinaryResponse(Stream s, string filename, string mimetype)
  {
      Response.Clear();
      Response.Buffer = true;

      Response.AddHeader("Content-Length", s.Length.ToString());
      Response.AddHeader("Content-Disposition", "inline; filename=" + filename.Replace(" ", "_"));
      Response.ContentType = mimetype;

      s.CopyTo(Response.OutputStream);
      Response.End();
  }
  // other functions…
}
Also the GetMandelbrotSet() method is declare inside H.cshtml page. It is a classic Mandelbrot algorithm; w and h are respectively the width and the height of the image, minr and mini are the coordinates of the lower-left Complex point and maxr is the Real part of the rightmost point, maxiter is the maximum number of iterations for each single point in the complex plane.

public static int[][] GetMandelbrotSet(
            int w, int h, double minr, double maxr, double mini, long maxiter)
{
    var image = new int[w][];
    for (int i = 0; i < w; i++)
        image[i] = new int[h];

    //Boring implementation details about generating a Mandelbrot fractal
    //...

    return image;
}
In the next article I will describe how I implemented a zooming capability using jQuery and javascript.
Edit: I finally published the second part of the article .

Stay tuned and happy programming!

mandel_-0_794068504594819_-0_682957393483708_0_228786727456941mandel_-0_807063956186762_-0_794718277174417_0_175446076775865mandel_-0_656811782542777_-0_655440040430294_0_343173133450913

No comments: