Saturday, December 22, 2007

Image Resizing

Sometimes you need to process the users' uploaded images in your web application so that it doesn't take too much space. This can be done either by resizing the uploaded image, saving it in a specific format or may be both.

The following is a code snippet for resizing images and saving it in *.jpeg format. The method take the image file to be resized as a stream, the destination path, the file name to save the image as and the maximum side size of the image (i.e the output image should fit a square of this maximum side size).


public static void ResizeImage(Stream originalImageStream, string destinationFilePath,
string destinationFileName, ImageEncoding saveEncoding, int maxSideSize)
{
int intNewWidth;
int intNewHeight;

Bitmap original = new Bitmap(originalImageStream); // your original image

//Set the image format
ImageFormat fmtImageFormat = original.RawFormat;

//Get the image original width and height
int intOldWidth = original.Width;
int intOldHeight = original.Height;

//Determine if Landscape or Portrait
int intMaxSide;

if (intOldWidth >= intOldHeight)
{
intMaxSide = intOldWidth;
}
else
{
intMaxSide = intOldHeight;
}


if (intMaxSide > maxSideSize)
{
//set new width and height
double dblCoef = maxSideSize / (double)intMaxSide;

intNewWidth = Convert.ToInt32(dblCoef * intOldWidth);
intNewHeight = Convert.ToInt32(dblCoef * intOldHeight);
}
else
{
intNewWidth = intOldWidth;
intNewHeight = intOldHeight;
}


Size resolution = new Size(intNewWidth, intNewHeight); // size of your thumbnail

Image thumbnail = new Bitmap(original, resolution);

Graphics g = Graphics.FromImage(thumbnail);

// The InterpolationMode was the catalyst to eliminate pixelation.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.SmoothingMode = SmoothingMode.HighQuality;

g.DrawImage(original, new Rectangle(0, 0, thumbnail.Size.Width, thumbnail.Size.Height));


// Prepare for a controlled-quality JPEG export
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
Encoder jpegEncoder = Encoder.Quality;
EncoderParameters jpegEncoderParameters = new EncoderParameters(1);
EncoderParameter jpegEncoderQuality = new EncoderParameter(jpegEncoder, 100L /*jpegQuality*/);

jpegEncoderParameters.Param[0] = jpegEncoderQuality;

thumbnail.Save(destinationFilePath + destinationFileName + ".jpg", jpegCodec, jpegEncoderParameters);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

You will have to get the appropriate codec information to save the image.

ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
1

The following is the implementation of GetEncoderInfo.
private static ImageCodecInfo GetEncoderInfo(string encoderString)
{
foreach (ImageCodecInfo info in ImageCodecInfo.GetImageEncoders())
{
if (info.MimeType == encoderString)
return info;
}

return null;
}
1
2
3
4
5
6
7
8
9
10


Simply you loop through all the encoders in ImageCodecInfo to find JPEG codec info. Other codecs info can also be retrieved for other image types like PNG, JIF and BMP.

The interesting point is in specifying the quality of your output image so that you avoid the pixelation problem and make your output image looks smooth. You declare a new Encoder Parameter with the required quality of your output image. Then you pass the encoding parameters when saving the final resized image.

// Prepare for a controlled-quality JPEG export
ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");
Encoder jpegEncoder = Encoder.Quality;
EncoderParameters jpegEncoderParameters = new EncoderParameters(1);
EncoderParameter jpegEncoderQuality = new EncoderParameter(jpegEncoder, 100L /*jpegQuality*/);

jpegEncoderParameters.Param[0] = jpegEncoderQuality;
1
2
3
4
5
6
7

The quality encoder parameter may have varying values (i.e. 25L, 50L, 75L and 100L). You will have to tune it to balance the quality with the output image size.

Another point to mention that there are many other interesting encoders you can make use of like Encoder.Transformation - which allowing you to rotate or swap your images. You can find more information here.

0 comments: