- Posted by liammclennan on May 21, 2009
In this post I will present a service class for resizing and saving an image. The service has one public method, ResizeAndSave() which accepts a stream, a filename and a directory to save the file to. It uses a simple algorithm to rescale the image to fit into a maximum rectangle and then performs the actual resize using System.Drawing, and returns the dimensions of the resized image.
public class ImageService : IImageService
{
private readonly IFileSystem fileSystem;
private const int LARGEST_WIDTH = 400;
private const int LARGEST_HEIGHT = 500;
public ImageService(IFileSystem fileSystem)
{
this.fileSystem = fileSystem;
}
public Rectangle ResizeAndSave(Stream input, string filename, string toDirectory)
{
using (Image image = Image.FromStream(input))
{
Rectangle scaledRectangle = (image.Width > LARGEST_WIDTH)
? ScaleByWidth(image.Width, image.Height, LARGEST_WIDTH)
: new Rectangle(0, 0, image.Width, image.Height);
if (scaledRectangle.Height > LARGEST_HEIGHT)
{
scaledRectangle = ScaleByHeight(scaledRectangle.Width, scaledRectangle.Height, LARGEST_HEIGHT);
}
Bitmap newImage = new Bitmap(scaledRectangle.Width, scaledRectangle.Height, image.PixelFormat);
Graphics toDrawOn = Graphics.FromImage(newImage);
toDrawOn.CompositingQuality = CompositingQuality.HighQuality;
toDrawOn.SmoothingMode = SmoothingMode.HighQuality;
toDrawOn.InterpolationMode = InterpolationMode.HighQualityBicubic;
toDrawOn.DrawImage(image, scaledRectangle);
fileSystem.Write(ConvertImageToMemoryStream(newImage).ToArray(), toDirectory, filename);
newImage.Dispose();
toDrawOn.Dispose();
return scaledRectangle;
}
}
private static MemoryStream ConvertImageToMemoryStream(Image image)
{
var stream = new MemoryStream();
image.Save(stream, image.RawFormat);
return stream;
}
private static Rectangle ScaleByWidth(int originalWidth, int originalHeight, int newWidth)
{
float scalingFactor = (float)newWidth / (float)originalWidth;
float newHeight = originalHeight * scalingFactor;
return new Rectangle(0, 0, newWidth, (int)newHeight);
}
private static Rectangle ScaleByHeight(int originalWidth, int originalHeight, int newHeight)
{
float scalingFactor = (float)newHeight / (float)originalHeight;
float newWidth = originalWidth * scalingFactor;
return new Rectangle(0, 0, (int)newWidth, newHeight);
}
}
The actual file writing is delegated to the IFileSystem service, which is implemented like so:
public class FileSystem : IFileSystem
{
public void Write(byte[] data, string directoryPath, string fileName)
{
if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
File.WriteAllBytes(directoryPath + fileName, data);
}
}