title: Image Resizing Performance: System.Drawing vs System.Windows.Media
body: <p>I've got a situation where I need to resize a large number of images. These images are stored as .jpg files on the file system currently, but I expect to just have byte[] in memory later on in the project. The source image size is variable, but the output should be 3 different predetermined sizes. Aspect ratios should be preserved, padding the original image with white space (ie, a really tall image would be resized to fit within the square target image size, with large areas of white on the left and right).</p>
  
  <p>I initially built the project targeting .NET 2.0, and using System.Drawing classes to perform the load/resize/save. Relevant code includes:</p>
  
  <pre><code>original = Image.FromFile(inputFile); //NOTE: Reused for each of the 3 target sizes
  Bitmap resized = new Bitmap(size, size);
  //Draw the image to a new image of the intended size
  Graphics g = Graphics.FromImage(resized);
  g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
  g.Clear(Color.White);
  g.DrawImage(original, center - width / 2f, center - height / 2f, width, height);
  g.Dispose();
  //Save the new image to the output path
  resized.Save(outputFile, ImageFormat.Jpeg);
  </code></pre>
  
  <p>I wanted to port this project to .NET 3.5, so tried using the System.Windows.Media classes to perform the same function. I got it working, however performance is terrible; processing time per image is about 50x longer. The vast majority of the time is spent loading the image. Relevant code includes:</p>
  
  <pre><code>BitmapImage original = new BitmapImage(); //Again, reused for each of the 3 target sizes
  original.BeginInit();
  original.StreamSource = new MemoryStream(imageData); //imageData is a byte[] of the data loaded from a FileStream
  original.CreateOptions = BitmapCreateOptions.None;
  original.CacheOption = BitmapCacheOption.Default;
  original.EndInit(); //Here's where the vast majority of the time is spent
  original.Freeze();
  
  // Target Rect for the resize operation
  Rect rect = new Rect(center - width / 2d, center - height / 2d, width, height);
  
  // Create a DrawingVisual/Context to render with
  DrawingVisual drawingVisual = new DrawingVisual();
  using (DrawingContext drawingContext = drawingVisual.RenderOpen())
  {
      drawingContext.DrawImage(original, rect);
  }
  
  // Use RenderTargetBitmap to resize the original image
  RenderTargetBitmap resizedImage = new RenderTargetBitmap(
      size, size,                         // Resized dimensions
      96, 96,                             // Default DPI values
      PixelFormats.Default);              // Default pixel format
  resizedImage.Render(drawingVisual);
  
  // Encode the image using the original format and save the modified image
  SaveImageData(resizedImage, outputFile);
  </code></pre>
  
  <p>Am I doing something wrong here, to take so much time? I've tried just using the constructor on BitmapImage that takes a URI, same performance issue there. Anyone done anything like this before, know if there's a more performance-minded way to do this? Or am I just going to need to use System.Drawing still? Thanks!</p>