Cropping in GDI+

Warning: There will be a few extremely elementary posts for anyone who's worked with ASP.NET, GDI+, or JavaScript already. However, they're brand new areas to me so this blog is going to double as a place where I can jot down concepts as they're learnt.

In what seems like a lifetime ago, I did a "bit" of work with pixels and image processing for this little product. All of it was written to be cross-platform so most of the code was C and looked something like this:

 void crop (unsigned long * src, unsigned long srcWidth, unsigned long ** dest, 
                 Rect cropArea)
{
  *dest = new unsigned long[cropArea.Width * cropArea.Height]();
  for (int i = cropArea.top; i < cropArea.bottom; i++)
  {
    long *scanline = src + (srcWidth * i) + cropArea.left;

    // copy pixels, unroll loops if necessary, etc...
  }
}

Inveitably you got extremely comfortable with pointer arithmetic and enjoyed being right next to the pixels every step of the way. Yes; "enjoyed".

All the frame data came out of QuickTime as uncompressed ARGB (or was it RGBA) and then we'd process them to our heart's content. I think the most interesting algorithm I wrote was to perform reverse 3:2 pulldown to transform video footage into progressive frames.

One of the first blocks I needed for my control was the abillity to crop images in C#. With a bit of help from live.com search (yes it works pretty well these days) I was able to rustle up some information on the Image, Bitmap, and Graphics classes. They seemed pretty straightforward, and a few minutes later I had this snippet:

 Image largeImage = Image.FromFile("clouds_large.jpg");

Bitmap croppedBitmap = new Bitmap(200, largeImage.Height);
Graphics croppedGraphic = Graphics.FromImage(croppedBitmap);

Rectangle part = new Rectangle(0, 0, 200, largeImage.Height);
croppedGraphic.DrawImage(largeImage, 0, 0, part, GraphicsUnit.Pixel);
            
croppedBitmap.Save("cropped.bmp", ImageFormat.Bmp);

Those of you who have written code like this are no doubt already shaking your heads and wondering what sort of people Microsoft employ. I was shaking my head as to why the cropped image always looked extrapolated. A short while later it dawned on me: different image resolutions. Being one of those things I only had to deal with fleetingly in the past, it took a while for the gears to start moving.

Sure enough, my source image was 96dpi and the Bitmap being created was 72dpi. One more magical line added, and happy days were here again.

 // Very Important!!
croppedBitmap.SetResolution(largeImage.HorizontalResolution,
                                              largeImage.VerticalResolution);