调整图像质量的大小

时间:2009-07-21 22:23:43

标签: c# graphics image-manipulation gdi

我写了一个简单的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)

simple http://img189.imageshack.us/img189/2137/simpleresize.jpg

我调整大小(55KB)

complex http://img12.imageshack.us/img12/4023/complexresize.jpg

2 个答案:

答案 0 :(得分:4)

我发现这个代码片段(对不起,我已经忘记了源代码)可能对您有所帮助:

// Create parameters
EncoderParameters params = new EncoderParameters (1);

// Set quality (100)
params.Param[0] = new EncoderParameter(Encoder.Quality, 100);

// Create encoder info
ImageCodecInfo codec = null;
foreach (ImageCodecInfo codectemp in ImageCodecInfo.GetImageDecoders())
{
    if (codectemp.MimeType == "image/jpeg")
    {
        codec = codectemp;
        break;
    }
}

// Check
if (codec == null)
    throw new Exception("Codec not found for image/jpeg");

// Save
image.Save(filename, codec, params);

答案 1 :(得分:2)

我的第一个想法是.NET的jpeg编码器即使在最高质量设置下也使用色度子采样,因此颜色信息以半分辨率存储。据我所知,该设置是硬编码的。但这并不能解释为什么你会在第二个例子中获得更好的质量。除非在第二个版本中它没有使用抗锯齿,否则会产生更清晰(但质量更低)的图像,并且这些文物会被忽视。

编辑:dst.Save(m,格式);看起来像你的问题。您将其编码为jpeg,默认质量(不是100%),然后立即将其解码回图像。 dst已经是一个Image(Bitmap类继承自Image),所以你可以按原样返回它