收缩图像时如何才能获得更好的效果 [英] How can I get better results when shrinking an image

查看:140
本文介绍了收缩图像时如何才能获得更好的效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm scaling images down in c#, and I've compared my methods with the best method in Photoshop cs5 and cannot replicate it.

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

In PS i'm using bicubic sharper, which looks really good. However, when trying to do the same in c# I don't get as high quality results. I've tried bicubic interpolation as well as HQ bicubic, smoothing mode HQ/None/AA. Composition modes, I've tried about 50 different variations and each one comes out pretty close to the image on the right.

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

You'll notice the pixelation on her back and around the title, as well as the authors name not coming out too well.

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

(Left is PS, right is c#.)

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

It seems that c# bicubic does too much smoothing even with smoothing set to none. I've been playing around with many variations of the following code:

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

编辑:这里要求的是起始图像(1mb)。

As requested here is the starting image (1mb).

推荐答案

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

Perhaps I am missing something, but I have typically used the following code below to resize/compress JPEG Images. Personally, I think the result turned out pretty well based on your source image. The code doesn't handle a few edge cases concerning input parameters, but overall gets the job done (I have additional extension methods for Cropping, and Combining image transformations if interested).

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

Image Scaled to 25% original size and using 90% Compression. (~30KB output file)

图像缩放扩展方法:

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,直到图像被处理完毕。如果您反映在MemoryStream上的Dispose的实现,它实际上是保存到不显式调用dispose。唯一的选择是将图像/内存流包装在实现Image / IDisposable的类的自定义实现中。

NOTE: For anyone who may comment, you cannot dispose the MemoryStream created in the Compress method until after the image is disposed. If you reflect in to the implementation of Dispose on MemoryStream, it is actually save to not explicitly call dispose. The only alternative would be to wrap the image/memory stream in a custom implementation of a class that implements Image/IDisposable.

这篇关于收缩图像时如何才能获得更好的效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆