Introduction
At times, there is a need to crop images at the center. For example, you need to store equal size Avatar images for users, but do not want to force users to first crop their images. You can instead allow them to use images of any dimension but process them at the server side to create equal sized images (having Avatar of different sizes on a site does not seem that great an idea!). A more elaborate solution would be to allow the user to select the crop region, but for simple needs that's overkill and waste of user time.
For a live demo of this technique, visit this jigsaw puzzle site page, where you can see equally sized user Avatars.
The Code
And here is the code that saves the images (.jpg in this case, but you can use other supported formats if you so wished). The last parameter specifies the path where the cropped image will be saved on disk.
public bool SaveCroppedImage(Image image, int maxWidth, int maxHeight, string filePath)
{
ImageCodecInfo jpgInfo = ImageCodecInfo.GetImageEncoders()
.Where(codecInfo =>
codecInfo.MimeType == "image/jpeg").First();
Image finalImage = image;
System.Drawing.Bitmap bitmap = null;
try
{
int left = 0;
int top = 0;
int srcWidth = maxWidth;
int srcHeight = maxHeight;
bitmap = new System.Drawing.Bitmap(maxWidth, maxHeight);
double croppedHeightToWidth = (double)maxHeight / maxWidth;
double croppedWidthToHeight = (double)maxWidth / maxHeight;
if (image.Width > image.Height)
{
srcWidth = (int)(Math.Round(image.Height * croppedWidthToHeight));
if (srcWidth < image.Width)
{
srcHeight = image.Height;
left = (image.Width - srcWidth) / 2;
}
else
{
srcHeight = (int)Math.Round(image.Height * ((double)image.Width/srcWidth));
srcWidth = image.Width;
top = (image.Height - srcHeight) / 2;
}
}
else
{
srcHeight = (int)(Math.Round(image.Width * croppedHeightToWidth));
if (srcHeight < image.Height)
{
srcWidth = image.Width;
top = (image.Height - srcHeight) / 2;
}
else
{
srcWidth = (int)Math.Round(image.Width * ((double)image.Height / srcHeight));
srcHeight = image.Height;
left = (image.Width - srcWidth) / 2;
}
}
using (Graphics g = Graphics.FromImage(bitmap))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(image, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
new Rectangle(left, top, srcWidth, srcHeight), GraphicsUnit.Pixel);
}
finalImage = bitmap;
}
catch { }
try
{
using (EncoderParameters encParams = new EncoderParameters(1))
{
encParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)100);
finalImage.Save(filePath, jpgInfo, encParams);
return true;
}
}
catch { }
if (bitmap != null)
{
bitmap.Dispose();
}
return false;
}
Here's how an ASP.NET MVC Action method might call the above function:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase imageFile)
{
SaveCroppedImage(Image.FromStream(imageFile.InputStream),
100, 100, @"C:\Temp\image.jpg");
return View();
}