收缩图像时如何才能获得更好的效果

The*_*Man 10 c# image-processing

我在c#中缩小图像,并且我将我的方法与Photoshop cs5中的最佳方法进行了比较,并且无法复制它.

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

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

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

在此输入图像描述

似乎c#bicubic即使平滑设置为无,也会进行太多平滑处理.我一直在玩下面代码的许多变体:

 g.CompositingQuality = CompositingQuality.HighQuality;
 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
 g.PixelOffsetMode = PixelOffsetMode.None;
 g.SmoothingMode = SmoothingMode.None;
Run Code Online (Sandbox Code Playgroud)

编辑:这里要求的是起始图像(1mb). 在此输入图像描述

Chr*_*ter 12

也许我遗漏了一些东西,但我通常使用下面的代码来调整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;
}
Run Code Online (Sandbox Code Playgroud)

压缩扩展方法:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

  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");
Run Code Online (Sandbox Code Playgroud)

注意: 对于可能发表评论的任何人,您无法处理在Compress方法中创建的MemoryStream,直到图像被处理完毕.如果您参与MemoryStream上Dispose的实现,实际上是保存为不显式调用dispose.唯一的替代方法是将图像/内存流包装在实现Image/IDisposable的类的自定义实现中.