.NET - 调整大小后图像周围的边框

5
我正在尝试在.NET中调整图像大小,但调整后的图像周围会出现淡黑色边框。我找到了一篇文章 - http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/cf765094-c8c1-4991-a1f3-cecdbd07ee15/,其中有人说将目标矩形大于画布可以解决此问题,但这对我不起作用。它消除了顶部和左侧的边框,但右侧和底部仍然存在,并且是完整的1像素厚的黑色。

我是否漏掉了什么?我的代码如下。

Image image = ... // this is a valid image loaded from the source
Rectangle srcRectangle = new Rectangle(0,0,width, height);
        Size croppedFullSize = new Size(width+3,height+3);
        Rectangle destRect = new Rectangle(new Point(-1,-1), croppedFullSize);
        using(Bitmap newImage = new Bitmap(croppedFullSize.Width, croppedFullSize.Height, format))
        using(Graphics Canvas = Graphics.FromImage(newImage)) {
            Canvas.SmoothingMode = SmoothingMode.AntiAlias;
            Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
            Canvas.PixelOffsetMode = PixelOffsetMode.HighQuality;
            Canvas.FillRectangle(Brushes.Transparent, destRect);
            Canvas.DrawImage(image, destRect, srcRectangle, GraphicsUnit.Pixel);


            newImage.Save(filename, image.RawFormat);
        }
3个回答

13

只需要向DrawImage方法提供一个ImageAttributes实例,其中WrapMode设置为TileFlipXY即可。这将防止边缘与背景颜色混合。

如果您需要示例代码,并且希望该代码不像其他答案那样泄漏内存,请参考此gist


1
太好了!我只需要从你的代码中拿一行,就解决了我的丑陋边框问题,谢谢!g.PixelOffsetMode = PixelOffsetMode.HighQuality; - Magnus Smith
TileFlipXY实际上是完全解决它的方法,这个问题有两个潜在的原因。您尝试过调整灰度图像的大小并将其放置在相同颜色的背景下吗? - Lilith River

3

尝试像这样使用,我想我从未得到过黑边...

如果你想使用System.Drawing库:

using (var sourceBmp = new Bitmap(sourcePath))
{
  decimal aspect = (decimal)sourceBmp.Width / (decimal)sourceBmp.Height;
  int newHeight = (int)(newWidth / aspect);

   using (var destinationBmp = new Bitmap(newWidth, newHeight))
   {
     using (var destinationGfx = Graphics.FromImage(destinationBmp))
     {
       destinationGfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
       destinationGfx.DrawImage(sourceBmp, new Rectangle(0, 0, destinationBmp.Width, destinationBmp.Height));
       destinationBmp.Save(destinationPath, ImageFormat.Jpeg);
      }
    }
}

或者您可以使用 WPF 来完成同样的操作,示例如下:

using (var output = new FileStream(outputPath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
{
   var imageDecoder = BitmapDecoder.Create(inputStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
   var imageFrame = imageDecoder.Frames[0];

   decimal aspect = (decimal)imageFrame.Width / (decimal)imageFrame.Height;
   var height = (int)(newWidth / aspect);

   var imageResized = new TransformedBitmap(imageFrame,new ScaleTransform(
                                                                 newWidth / imageFrame.Width * Dpi / imageFrame.DpiX,
                                                                 height / imageFrame.Height * Dpi / imageFrame.DpiY, 0, 0));

   var targetFrame = BitmapFrame.Create(imageResized);

   var targetEncoder = new JpegBitmapEncoder();
   targetEncoder.Frames.Add(targetFrame);
   targetEncoder.QualityLevel = 80;
   targetEncoder.Save(output);
}

我建议采用WPF方式。压缩和质量似乎更好...


我仔细阅读了代码,第一个版本与我现在拥有的版本完全相同(不起作用)。然而,第二种方法确实有效。将对PresentationCore和System.Xaml的引用添加到ASP.NET项目中感觉有点不好,但既然它有效,为什么不这样做呢… - Echilon

3
对我来说,问题出在位图参数上。应该使用如下代码:
new Bitmap(width, height, PixelFormat.Format32bppPArgb);

只需将PixelFormat移除即可:

new Bitmap(width, height);

那时一切都很好。

使用 PixelFormat 后,我在顶部和左侧边框上有黑色边框。然后我尝试了 g.PixelOffsetMode = PixelOffsetMode.HighQuality; 开始看起来还不错。但是后来我注意到整个图像周围有浅灰色的边框。


这对我来说很有效,非常简单的方法只需删除此PixelFormat.Format32bppPArgb。 - LittleDragon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接