调整图像大小 降低图像质量
我编写了一个简单的 PhotoEditor 帮助程序类来缩小和裁剪上传到我的网站的图像。 一切正常,但当图像保存到文件时,我发现质量不令人满意。 我已经阅读了您可以调整的不同设置,下面是我调整大小的设置,裁剪是相同的。
public Image ResizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercentW = (size.Width/(float) sourceWidth);
float nPercentH = (size.Height/(float) sourceHeight);
float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;
var destWidth = (int) (sourceWidth*nPercent);
var destHeight = (int) (sourceHeight*nPercent);
var src = imgToResize;
using (var dst = new Bitmap(destWidth, destHeight, imgToResize.PixelFormat))
{
dst.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);
using (var g = Graphics.FromImage(dst))
{
var mime = GetMimeType(imgToResize);
ImageFormat format;
if (mime == "image/gif" || mime == "image/png")
{
//convert all gif to png, better resize quality
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, dst.Width, dst.Height);
format = ImageFormat.Png;
}
else
{
//jpeg
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
format = ImageFormat.Jpeg;
}
g.DrawImage(src, 0, 0, dst.Width, dst.Height);
// At this point the new bitmap has no MimeType
// Need to output to memory stream
var m = new MemoryStream();
dst.Save(m, format);
var img = Image.FromStream(m);
return img;
}
}
}
正如您所看到的,我正在使用插值、平滑等建议的设置。我还以质量 100 保存 jpeg
。即使将大小调整为原始大小的 75%,生成的图像也有明显的模糊和伪影。 我环顾四周,这是推荐的方式。 我找到了一种简单的调整大小的方法,并决定尝试一下。
Bitmap NewImg = new Bitmap(original, new Size(387,257));
editor.SaveImage(@"C:\simpleResize.jpg", NewImg, ImageFormat.Jpeg);
令人惊讶的是,这会产生更好的图像,尽管它的内存占用量大了约 30%。
我的问题是,有什么区别以及我在调整大小例程中缺少哪些设置可能会导致更丑陋的结果。 我想让我的调整大小例程产生与简单调整大小完全相同的结果。
非常感谢您的帮助。 这是我第一次涉足图像处理。
编辑
简单调整大小(82KB)
简单的http://img189。 imageshack.us/img189/2137/simpleresize.jpg
我的调整大小 (55KB)
I have written a simple PhotoEditor helper class to downscale and crop images uploaded to my website. Everything is working but I am seeing unsatisfactory quality when the image is saved to file. I have read up on the different settings you can tweak below is my setup for resizing, cropping is identical.
public Image ResizeImage(Image imgToResize, Size size)
{
int sourceWidth = imgToResize.Width;
int sourceHeight = imgToResize.Height;
float nPercentW = (size.Width/(float) sourceWidth);
float nPercentH = (size.Height/(float) sourceHeight);
float nPercent = nPercentH < nPercentW ? nPercentH : nPercentW;
var destWidth = (int) (sourceWidth*nPercent);
var destHeight = (int) (sourceHeight*nPercent);
var src = imgToResize;
using (var dst = new Bitmap(destWidth, destHeight, imgToResize.PixelFormat))
{
dst.SetResolution(imgToResize.HorizontalResolution, imgToResize.VerticalResolution);
using (var g = Graphics.FromImage(dst))
{
var mime = GetMimeType(imgToResize);
ImageFormat format;
if (mime == "image/gif" || mime == "image/png")
{
//convert all gif to png, better resize quality
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, dst.Width, dst.Height);
format = ImageFormat.Png;
}
else
{
//jpeg
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
format = ImageFormat.Jpeg;
}
g.DrawImage(src, 0, 0, dst.Width, dst.Height);
// At this point the new bitmap has no MimeType
// Need to output to memory stream
var m = new MemoryStream();
dst.Save(m, format);
var img = Image.FromStream(m);
return img;
}
}
}
As you can see I am using the suggested settings for Interpolation, Smoothing etc. I am also saving the jpeg with quality 100.
The resultant image has noticeable blurring and artefacts even when resizing down to a modest 75% of its original size. I looked around and this is the recommended way. I found a simplistic way to resize and decided to give that a go.
Bitmap NewImg = new Bitmap(original, new Size(387,257));
editor.SaveImage(@"C:\simpleResize.jpg", NewImg, ImageFormat.Jpeg);
Surprisingly this produces a much nicer image although it is quite a bit bigger ~30% larger in memory footprint.
My question is, what's the difference and what setting am I missing on my resize routine that could account for the uglier result. Id like to get my resize routine to produce the exact same result as the simple resize.
Your help is much appreciated. This is my first foray into image processing.
EDIT
Simple Resize (82KB)
simple http://img189.imageshack.us/img189/2137/simpleresize.jpg
My Resize (55KB)
complex http://img12.imageshack.us/img12/4023/complexresize.jpg
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我发现这个示例代码片段(抱歉我忘记了来源)可能对您有帮助:
I found this example snippet of code (sorry I've forgotten the source) that might help you:
我的第一个想法是 .NET 的 jpeg 编码器即使在最高质量设置下也使用色度子采样,因此颜色信息以一半分辨率存储。 据我所知,该设置是硬编码的。 但这并不能解释为什么在第二个示例中会获得更好的质量。 除非在第二个版本中它没有使用抗锯齿功能,从而提供更清晰(但质量较低)的图像,并且伪影不会被注意到。
编辑: dst.Save(m, format); 看起来像你的问题。 您将其编码为 jpeg,具有默认质量(不是 100%),然后立即将其解码回图像。 dst 已经是一个 Image (Bitmap 类继承自 Image),所以你可以按原样返回它
My first thought was that .NET's jpeg encoder uses chroma subsampling even at the highest quality setting, so color information is stored at half resolution. The setting is hard-coded as far as I can tell. But that wouldn't explain why you would get better quality in the second example. Unless maybe in the 2nd it didn't use antialiasing, giving a sharper (but lower quality) image and the artifacts went unnoticed.
Edit: The dst.Save(m, format); looks like your problem. You're encoding it as jpeg there, with default quality (not 100%), then immediately decoding it back to an image. dst is already an Image (Bitmap class inherits from Image), so you can just return it as-is