Perhaps I am missing something, but I have typically used the following code below to resize/compress JPEG Images. Personally, I think the result turned out pretty well based on your source image. The code doesn't handle a few edge cases concerning input parameters, but overall gets the job done (I have additional extension methods for Cropping, and Combining image transformations if interested).
Image Scaled to 25% original size and using 90% Compression. (~30KB output file)
Image Scaling Extension Methods:
public static Image Resize(this Image image, Single scale)
{
if (image == null)
return null;
scale = Math.Max(0.0F, scale);
Int32 scaledWidth = Convert.ToInt32(image.Width * scale);
Int32 scaledHeight = Convert.ToInt32(image.Height * scale);
return image.Resize(new Size(scaledWidth, scaledHeight));
}
public static Image Resize(this Image image, Size size)
{
if (image == null || size.IsEmpty)
return null;
var resizedImage = new Bitmap(size.Width, size.Height, image.PixelFormat);
resizedImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var g = Graphics.FromImage(resizedImage))
{
var location = new Point(0, 0);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(image, new Rectangle(location, size), new Rectangle(location, image.Size), GraphicsUnit.Pixel);
}
return resizedImage;
}
Compression Extension Method:
public static Image Compress(this Image image, Int32 quality)
{
if (image == null)
return null;
quality = Math.Max(0, Math.Min(100, quality));
using (var encoderParameters = new EncoderParameters(1))
{
var imageCodecInfo = ImageCodecInfo.GetImageEncoders().First(encoder => String.Compare(encoder.MimeType, "image/jpeg", StringComparison.OrdinalIgnoreCase) == 0);
var memoryStream = new MemoryStream();
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, Convert.ToInt64(quality));
image.Save(memoryStream, imageCodecInfo, encoderParameters);
return Image.FromStream(memoryStream);
}
}
Usage:
using(var source = Image.FromFile(@"C:~Source.jpg"))
using(var resized = source.Resize(0.25F))
using(var compressed = resized.Compress(90))
compressed.Save(@"C:~Output.jpg");
NOTE:
For anyone who may comment, you cannot dispose the MemoryStream created in the Compress method until after the image is disposed. If you reflect in to the implementation of Dispose on MemoryStream, it is actually save to not explicitly call dispose. The only alternative would be to wrap the image/memory stream in a custom implementation of a class that implements Image/IDisposable.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…