2009-07-21 121 views
2

我已经编写了一个简单的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; 
      } 
     } 
    } 

正如你可以看到我使用插值建议的设置,平滑等等。我还保存JPEG质量100

所得到的图像具有明显的模糊和文物甚至向下调整时其原始尺寸的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

+1

dst.Save(m,format);看起来像你的问题。您将它编码为jpeg,默认质量(不是100%),然后立即将其解码为图像。 dst已经是一个Image(位图类继承自Image),所以你可以直接返回它。 – David 2009-07-22 05:17:18

+0

嗨大卫。你是对的。我在这一步背后的推理是,mimetype是最终图像的一部分。我暂时将该图像存储在会话中,并希望能够稍后检索它。如果您更新答案,请将其标记为已回答。 – madcapnmckay 2009-07-22 12:01:38

回答

2

我首先想到的是,.NET的JPEG编码器使用色度甚至在最高质量的settin下进行二次取样g,因此颜色信息以半分辨率存储。据我所知,该设置是硬编码的。但这并不能解释为什么你会在第二个例子中获得更好的质量。除非在第二天它没有使用抗锯齿功能,否则会产生更清晰(但质量更低)的图像,而且这些工件未被发现。

编辑:dst.Save(m,format);看起来像你的问题。您将它编码为jpeg,默认质量(不是100%),然后立即将其解码为图像。 DST已经是影像(Bitmap类从图片继承),所以你可以只返回它就好了

+0

感谢您的快速响应。我试图改变AA的设置,看看它是否有帮助,但它似乎不是人工制品的原因。我在简单的调整大小和复合体之间翻转了四分之一,并且仅在复合体上存在人工制品。 – madcapnmckay 2009-07-21 23:04:12

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);