Tutorial :Image resizing with GDI+



Question:

I'm really trying to nail out a little more performance out of this tidbit of code. It's not a heavly used bit of code but is used every time a new image is uploaded, and 4 times for each image (100px, 200px, 500px, 700px). So when there are any more than 2 or 3 images processing, it gets a little busy on the server. Also I'm trying to figure out how to make it correctly process images with a low resolution. Currently it just chops it off half way through, not plesent. Examples: Original, large, xLarge

public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)  {      using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))      {          Size newSize = CalculateDimensions(oldImage.Size, targetSize);            using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height, PixelFormat.Format32bppRgb))          {              newImage.SetResolution(oldImage.HorizontalResolution, oldImage.VerticalResolution);              using (Graphics canvas = Graphics.FromImage(newImage))              {                  canvas.SmoothingMode = SmoothingMode.AntiAlias;                  canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;                  canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;                  canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));                  MemoryStream m = new MemoryStream();                  newImage.Save(m, ImageFormat.Jpeg);                  return m.GetBuffer();              }          }        }  }    private static Size CalculateDimensions(Size oldSize, int targetSize)  {      Size newSize = new Size();      if (oldSize.Width > oldSize.Height)      {          newSize.Width = targetSize;          newSize.Height = (int)(oldSize.Height * (float)targetSize / (float)oldSize.Width);      }      else      {          newSize.Width = (int)(oldSize.Width * (float)targetSize / (float)oldSize.Height);          newSize.Height = targetSize;      }      return newSize;  }  

Thanks for and help!


Solution:1

The first thought that comes to mind is, have you thought about Multithreading it? i.e. calling this method for each image (or batch of images) in a separate thread? That way, if your server has a few cores you can get things done quicker. Just a thought...


Solution:2

(Threading is a great tip.)

Try to call your method with the smallest possible image as input each time, instead of the original image. If the original image is, say 2000px, then create the 700px image from it and then use your newly created 700px image to create the 500px, etc...

With the HighQualityBicubic setting I doubt that you'll notice any difference in the 100px image. (But it of course it needs to be verified.)


Solution:3

For completeness, here is the solution to the second part of the question which was never answered. When processing a low resolution image the image was being cut off. The solution now, seems obvious. The problem lies in this bit of code from above:

using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height,                                                       PixelFormat.Format32bppRgb))  

The problem being that I'm selecting the PixelFormat, not letting it be the format of the original image. The correct code is here:

public static byte[] ResizeImageFile(byte[] imageFile, int targetSize)  {      using (System.Drawing.Image oldImage = System.Drawing.Image.FromStream(new MemoryStream(imageFile)))      {          Size newSize = CalculateDimensions(oldImage.Size, targetSize);        using (Bitmap newImage = new Bitmap(newSize.Width, newSize.Height,                                                            oldImage.PixelFormat))      {          newImage.SetResolution(oldImage.HorizontalResolution,                                                      oldImage.VerticalResolution);          using (Graphics canvas = Graphics.FromImage(newImage))          {              canvas.SmoothingMode = SmoothingMode.AntiAlias;              canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;              canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;              canvas.DrawImage(oldImage, new Rectangle(new Point(0, 0), newSize));              MemoryStream m = new MemoryStream();              newImage.Save(m, ImageFormat.Jpeg);              return m.GetBuffer();          }      }       }  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »