Tuesday, April 10, 2012

Low (Resolution) and Order (of applying transformations)

I'm doing a project that involves taking huge images of 400,000,000 pixels, 20000 X 20000, 700 MB on disk, scaling them down and cutting them into reasonably sized tiles (512x512 pixels).

In this post I want to present how simple code re factoring involving merely changing the order of applying the same transformations rewarded an enormous X20 performance gain.

As a first step, I had to order extra 8GB RAM for my workstation. Once thay have arrived (eBay, 100$, 1 week) I could finally click the input file and display it on windows image preview. Before that, my workstation, initially having only 2GB, hang for 20 minutes every time I accidentally hovered over the file.

The next step was to realize that .NET 2.0 bitmap classes won't do the trick. But than I was surprised to discover that WPF BitmapSource and its sub-classes (System.Windows.Media.Imaging) are capable of handling these very large images so I built the code around them avoiding a native C++ bite-cruncher completely. This was a very good start. It made me very happy.

The third step was to wrap the cropped images in DICOM. This is a subject for a dedicated, yet to come, post about the new multi-frame objects and concatenations. Then came the last two steps that proved out to be challenging.

My initial code looked like this:

  1. Use ScaleTransform to down-scale the original image to the required resolution
  2. Loop over the down-scaled image on X and Y to do the tiling (The Cut function)
  3. Use CroppedBitmap to do the cropping (in the loop)

Here it is: