c# - 缩小图像时如何获得更好的结果

标签 c# image-processing

我正在用 C# 缩小图像,我已经将我的方法与 Photoshop cs5 中的最佳方法进行了比较,但无法复制它。

在 PS 中,我使用的是双三次锐化器,看起来非常好。然而,当尝试在 c# 中做同样的事情时,我没有得到高质量的结果。我尝试过双三次插值以及 HQ 双三次平滑模式 HQ/None/AA。合成模式,我尝试了大约 50 种不同的变化,每一种都非常接近右边的图像。

您会注意到她背部和标题周围的像素化,以及作者的名字不太好。

(左边是PS,右边是c#。)

enter image description here

似乎 c# bicubic 做了太多的平滑,即使平滑设置为无。我一直在研究以下代码的许多变体:

 g.CompositingQuality = CompositingQuality.HighQuality;
 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
 g.PixelOffsetMode = PixelOffsetMode.None;
 g.SmoothingMode = SmoothingMode.None;

编辑: 这里是起始图像 (1mb)。 enter image description here

最佳答案

也许我遗漏了什么,但我通常使用下面的代码来调整/压缩 JPEG 图像。就个人而言,我认为根据您的源图像,结果非常好。该代码不处理一些与输入参数有关的边缘情况,但总体上完成了工作(如果有兴趣,我还有其他扩展方法用于裁剪和组合图像转换)。

图像缩放为原始大小的 25%,并使用 90% 的压缩率。 (~30KB 输出文件)

SampleImage

图像缩放扩展方法:

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

压缩扩展方法:

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

用法:

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

注意: 对于可能发表评论的任何人,在处理图像之前,您不能处理在 Compress 方法中创建的 MemoryStream。如果反射(reflection)到MemoryStream上Dispose的实现,其实是省去了不显式调用dispose。唯一的选择是将图像/内存流包装在实现 Image/IDisposable 的类的自定义实现中。

关于c# - 缩小图像时如何获得更好的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6170912/

相关文章:

c# - Asp.Net MVC 中 Web API 的默认 Controller 操作

c# - ASP.NET Core 中的 System.Data.Entity.Spatial 替换

java - Java中的图像处理边缘检测

python - 将图像划分为 block

python - 使用 Python 进行视网膜血管分割

c# - 证书吊销列表 c#

c# - 类属性不可访问

c# - VS2010 中的单元测试

matlab - "Cut out"基于边缘检测的图像

python - OpenCV,Python : Eliminating eventual narrowing when stitching images